mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
Make new USE_BUFFERS command
Make a new USE_BUFFERS command to atomically send a buffer array to the remote client. We can use this to then clean up an old array and go to the PAUSED state if possible. Work on formats. Make one structure that can hold all video formats. Work on pipeline suspend and resume. Add jpeg support to v4l2. Work on enum_formats with a filter in v4l2.
This commit is contained in:
parent
7e858ff694
commit
b67c216a04
24 changed files with 688 additions and 514 deletions
|
|
@ -43,9 +43,6 @@
|
|||
typedef struct {
|
||||
bool cleanup;
|
||||
uint32_t id;
|
||||
int fd;
|
||||
off_t offset;
|
||||
size_t size;
|
||||
bool used;
|
||||
SpaBuffer *buf;
|
||||
} BufferId;
|
||||
|
|
@ -53,10 +50,8 @@ typedef struct {
|
|||
static void
|
||||
clear_buffer_id (BufferId *id)
|
||||
{
|
||||
munmap (id->buf, id->size);
|
||||
spa_memory_unref (&id->buf->mem.mem);
|
||||
id->buf = NULL;
|
||||
close (id->fd);
|
||||
id->fd = -1;
|
||||
}
|
||||
|
||||
struct _PinosStreamPrivate
|
||||
|
|
@ -822,45 +817,46 @@ parse_control (PinosStream *stream,
|
|||
spa_memory_unref (&p.mem);
|
||||
break;
|
||||
}
|
||||
case SPA_CONTROL_CMD_ADD_BUFFER:
|
||||
case SPA_CONTROL_CMD_USE_BUFFERS:
|
||||
{
|
||||
SpaControlCmdAddBuffer p;
|
||||
SpaControlCmdUseBuffers p;
|
||||
BufferId bid;
|
||||
SpaMemory *mem;
|
||||
unsigned int i;
|
||||
SpaControlBuilder builder;
|
||||
SpaControl control;
|
||||
|
||||
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
||||
break;
|
||||
|
||||
g_debug ("add buffer %d, %d", p.buffer_id, p.mem.mem.id);
|
||||
mem = spa_memory_find (&p.mem.mem);
|
||||
/* clear previous buffers */
|
||||
g_array_set_size (priv->buffer_ids, 0);
|
||||
|
||||
for (i = 0; i < p.n_buffers; i++) {
|
||||
bid.buf = p.buffers[i];
|
||||
bid.cleanup = false;
|
||||
bid.id = p.buffer_id;
|
||||
bid.offset = p.mem.offset;
|
||||
bid.size = p.mem.size;
|
||||
bid.buf = SPA_MEMBER (spa_memory_ensure_ptr (mem), p.mem.offset, SpaBuffer);
|
||||
bid.id = bid.buf->id;
|
||||
g_debug ("add buffer %d, %d", bid.id, bid.buf->mem.mem.id);
|
||||
|
||||
if (bid.id != priv->buffer_ids->len) {
|
||||
g_warning ("unexpected id %u found, expected %u", bid.id, priv->buffer_ids->len);
|
||||
priv->in_order = FALSE;
|
||||
}
|
||||
g_array_append_val (priv->buffer_ids, bid);
|
||||
g_signal_emit (stream, signals[SIGNAL_ADD_BUFFER], 0, p.buffer_id);
|
||||
break;
|
||||
g_signal_emit (stream, signals[SIGNAL_ADD_BUFFER], 0, bid.id);
|
||||
}
|
||||
case SPA_CONTROL_CMD_REMOVE_BUFFER:
|
||||
{
|
||||
SpaControlCmdRemoveBuffer p;
|
||||
BufferId *bid;
|
||||
|
||||
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
||||
break;
|
||||
|
||||
g_debug ("remove buffer %d", p.buffer_id);
|
||||
if ((bid = find_buffer (stream, p.buffer_id))) {
|
||||
bid->cleanup = TRUE;
|
||||
bid->used = TRUE;
|
||||
g_signal_emit (stream, signals[SIGNAL_REMOVE_BUFFER], 0, p.buffer_id);
|
||||
control_builder_init (stream, &builder);
|
||||
if (p.n_buffers) {
|
||||
add_state_change (stream, &builder, SPA_NODE_STATE_PAUSED);
|
||||
} else {
|
||||
add_state_change (stream, &builder, SPA_NODE_STATE_READY);
|
||||
}
|
||||
spa_control_builder_end (&builder, &control);
|
||||
|
||||
if (spa_control_write (&control, priv->fd) < 0)
|
||||
g_warning ("stream %p: error writing control", stream);
|
||||
|
||||
spa_control_clear (&control);
|
||||
break;
|
||||
}
|
||||
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
||||
|
|
@ -919,7 +915,6 @@ on_socket_condition (GSocket *socket,
|
|||
case G_IO_IN:
|
||||
{
|
||||
SpaControl *control = &priv->recv_control;
|
||||
guint i;
|
||||
|
||||
if (spa_control_read (control,
|
||||
priv->fd,
|
||||
|
|
@ -933,17 +928,6 @@ on_socket_condition (GSocket *socket,
|
|||
|
||||
parse_control (stream, control);
|
||||
|
||||
for (i = 0; i < priv->buffer_ids->len; i++) {
|
||||
BufferId *bid = &g_array_index (priv->buffer_ids, BufferId, i);
|
||||
if (bid->cleanup) {
|
||||
g_array_remove_index_fast (priv->buffer_ids, i);
|
||||
i--;
|
||||
priv->in_order = FALSE;
|
||||
}
|
||||
}
|
||||
if (!priv->in_order && priv->buffer_ids->len == 0)
|
||||
priv->in_order = TRUE;
|
||||
|
||||
spa_control_clear (control);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ calc_size (GstCapsFeatures *cf, GstStructure *cs, guint *n_infos, guint *n_range
|
|||
n_ranges[0] += c;
|
||||
n_datas[0] += (1 + c) * sizeof (uint32_t);
|
||||
}
|
||||
} else if (gst_structure_has_name (cs, "image/jpeg")) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +148,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
if (val) {
|
||||
SpaVideoFormat *sv = p;
|
||||
|
||||
spa_video_raw_fill_prop_info (&bpi[pi],
|
||||
spa_prop_info_fill_video (&bpi[pi],
|
||||
SPA_PROP_ID_VIDEO_FORMAT,
|
||||
SPA_PTRDIFF (p, f));
|
||||
|
||||
|
|
@ -171,7 +172,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
if (val || val2) {
|
||||
SpaRectangle *sv = p;
|
||||
|
||||
spa_video_raw_fill_prop_info (&bpi[pi],
|
||||
spa_prop_info_fill_video (&bpi[pi],
|
||||
SPA_PROP_ID_VIDEO_SIZE,
|
||||
SPA_PTRDIFF (p, f));
|
||||
|
||||
|
|
@ -224,7 +225,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
if (val) {
|
||||
SpaFraction *sv = p;
|
||||
|
||||
spa_video_raw_fill_prop_info (&bpi[pi],
|
||||
spa_prop_info_fill_video (&bpi[pi],
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||
SPA_PTRDIFF (p, f));
|
||||
|
||||
|
|
@ -284,7 +285,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
if (val) {
|
||||
SpaAudioFormat *sv = p;
|
||||
|
||||
spa_audio_raw_fill_prop_info (&bpi[pi],
|
||||
spa_prop_info_fill_audio (&bpi[pi],
|
||||
SPA_PROP_ID_AUDIO_FORMAT,
|
||||
SPA_PTRDIFF (p, f));
|
||||
|
||||
|
|
@ -307,7 +308,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
if (val) {
|
||||
SpaAudioLayout *sv = p;
|
||||
|
||||
spa_audio_raw_fill_prop_info (&bpi[pi],
|
||||
spa_prop_info_fill_audio (&bpi[pi],
|
||||
SPA_PROP_ID_AUDIO_LAYOUT,
|
||||
SPA_PTRDIFF (p, f));
|
||||
|
||||
|
|
@ -334,7 +335,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
if (val) {
|
||||
uint32_t *sv = p;
|
||||
|
||||
spa_audio_raw_fill_prop_info (&bpi[pi],
|
||||
spa_prop_info_fill_audio (&bpi[pi],
|
||||
SPA_PROP_ID_AUDIO_RATE,
|
||||
SPA_PTRDIFF (p, f));
|
||||
|
||||
|
|
@ -357,7 +358,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
if (val) {
|
||||
uint32_t *sv = p;
|
||||
|
||||
spa_audio_raw_fill_prop_info (&bpi[pi],
|
||||
spa_prop_info_fill_audio (&bpi[pi],
|
||||
SPA_PROP_ID_AUDIO_CHANNELS,
|
||||
SPA_PTRDIFF (p, f));
|
||||
|
||||
|
|
@ -376,6 +377,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
}
|
||||
pi++;
|
||||
}
|
||||
} else if (gst_structure_has_name (cs, "image/jpeg")) {
|
||||
f->media_type = SPA_MEDIA_TYPE_VIDEO;
|
||||
f->media_subtype = SPA_MEDIA_SUBTYPE_MJPG;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
|
@ -431,16 +435,21 @@ gst_caps_from_format (SpaFormat *format)
|
|||
GstCaps *res = NULL;
|
||||
|
||||
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
|
||||
SpaFormatVideo f;
|
||||
|
||||
spa_format_video_parse (format, &f);
|
||||
|
||||
if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
||||
SpaVideoRawFormat f;
|
||||
|
||||
spa_video_raw_format_parse (format, &f);
|
||||
|
||||
res = gst_caps_new_simple ("video/x-raw",
|
||||
"format", G_TYPE_STRING, gst_video_format_to_string (f.info.format),
|
||||
"width", G_TYPE_INT, f.info.size.width,
|
||||
"height", G_TYPE_INT, f.info.size.height,
|
||||
"framerate", GST_TYPE_FRACTION, f.info.framerate.num, f.info.framerate.denom,
|
||||
"format", G_TYPE_STRING, gst_video_format_to_string (f.info.raw.format),
|
||||
"width", G_TYPE_INT, f.info.raw.size.width,
|
||||
"height", G_TYPE_INT, f.info.raw.size.height,
|
||||
"framerate", GST_TYPE_FRACTION, f.info.raw.framerate.num, f.info.raw.framerate.denom,
|
||||
NULL);
|
||||
}
|
||||
else if (format->media_subtype == SPA_MEDIA_SUBTYPE_MJPG) {
|
||||
res = gst_caps_new_simple ("image/jpeg",
|
||||
"framerate", GST_TYPE_FRACTION, f.info.jpeg.framerate.num, f.info.jpeg.framerate.denom,
|
||||
NULL);
|
||||
}
|
||||
} else if (format->media_type == SPA_MEDIA_TYPE_AUDIO) {
|
||||
|
|
|
|||
|
|
@ -224,25 +224,32 @@ setup_node (PinosSpaV4l2Source *this)
|
|||
}
|
||||
|
||||
static void
|
||||
stop_pipeline (PinosSpaV4l2Source *this)
|
||||
pause_pipeline (PinosSpaV4l2Source *this)
|
||||
{
|
||||
PinosSpaV4l2SourcePrivate *priv = this->priv;
|
||||
PinosNode *node = PINOS_NODE (this);
|
||||
SpaResult res;
|
||||
SpaCommand cmd;
|
||||
|
||||
g_debug ("spa-v4l2-source %p: stopping pipeline", this);
|
||||
|
||||
if (priv->running) {
|
||||
priv->running = false;
|
||||
pthread_join (priv->thread, NULL);
|
||||
}
|
||||
g_debug ("spa-v4l2-source %p: pause pipeline", this);
|
||||
|
||||
cmd.type = SPA_COMMAND_PAUSE;
|
||||
if ((res = spa_node_send_command (node->node, &cmd)) < 0)
|
||||
g_debug ("got error %d", res);
|
||||
}
|
||||
|
||||
static void
|
||||
suspend_pipeline (PinosSpaV4l2Source *this)
|
||||
{
|
||||
PinosNode *node = PINOS_NODE (this);
|
||||
SpaResult res;
|
||||
|
||||
g_debug ("spa-v4l2-source %p: suspend pipeline", this);
|
||||
|
||||
if ((res = spa_node_port_set_format (node->node, 0, 0, NULL)) < 0) {
|
||||
g_warning ("error unset format output: %d", res);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_pipeline (PinosSpaV4l2Source *this)
|
||||
{
|
||||
|
|
@ -259,13 +266,14 @@ set_state (PinosNode *node,
|
|||
|
||||
switch (state) {
|
||||
case PINOS_NODE_STATE_SUSPENDED:
|
||||
suspend_pipeline (this);
|
||||
break;
|
||||
|
||||
case PINOS_NODE_STATE_INITIALIZING:
|
||||
break;
|
||||
|
||||
case PINOS_NODE_STATE_IDLE:
|
||||
stop_pipeline (this);
|
||||
pause_pipeline (this);
|
||||
break;
|
||||
|
||||
case PINOS_NODE_STATE_RUNNING:
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ struct _PinosLinkPrivate
|
|||
gboolean active;
|
||||
gboolean negotiated;
|
||||
gboolean allocated;
|
||||
gboolean started;
|
||||
|
||||
PinosPort *output;
|
||||
PinosPort *input;
|
||||
|
|
@ -227,14 +228,16 @@ do_negotiate (PinosLink *this)
|
|||
|
||||
g_debug ("link %p: doing set format", this);
|
||||
|
||||
priv->negotiated = TRUE;
|
||||
|
||||
again:
|
||||
if ((res = spa_node_port_enum_formats (priv->input_node,
|
||||
priv->input_port,
|
||||
&filter,
|
||||
NULL,
|
||||
&istate)) < 0) {
|
||||
g_warning ("error enum formats: %d", res);
|
||||
return res;
|
||||
g_warning ("error input enum formats: %d", res);
|
||||
goto error;
|
||||
}
|
||||
spa_debug_format (filter);
|
||||
|
||||
|
|
@ -247,26 +250,30 @@ again:
|
|||
ostate = NULL;
|
||||
goto again;
|
||||
}
|
||||
g_warning ("error enum formats: %d", res);
|
||||
return res;
|
||||
g_warning ("error output enum formats: %d", res);
|
||||
goto error;
|
||||
}
|
||||
spa_debug_format (format);
|
||||
|
||||
spa_format_fixate (format);
|
||||
|
||||
spa_debug_format (format);
|
||||
|
||||
if ((res = spa_node_port_set_format (priv->output_node, priv->output_port, 0, format)) < 0) {
|
||||
g_warning ("error set format output: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((res = spa_node_port_set_format (priv->input_node, priv->input_port, 0, format)) < 0) {
|
||||
g_warning ("error set format input: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
|
||||
priv->negotiated = TRUE;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
error:
|
||||
{
|
||||
priv->negotiated = FALSE;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -281,13 +288,15 @@ do_allocation (PinosLink *this)
|
|||
/* find out what's possible */
|
||||
if ((res = spa_node_port_get_info (priv->output_node, priv->output_port, &oinfo)) < 0) {
|
||||
g_warning ("error get port info: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
if ((res = spa_node_port_get_info (priv->input_node, priv->input_port, &iinfo)) < 0) {
|
||||
g_warning ("error get port info: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
|
||||
priv->allocated = TRUE;
|
||||
|
||||
spa_debug_port_info (oinfo);
|
||||
spa_debug_port_info (iinfo);
|
||||
|
||||
|
|
@ -311,7 +320,7 @@ do_allocation (PinosLink *this)
|
|||
priv->in_buffers,
|
||||
&priv->n_in_buffers)) < 0) {
|
||||
g_warning ("error alloc buffers: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
memcpy (priv->out_buffers, priv->in_buffers, priv->n_in_buffers * sizeof (SpaBuffer*));
|
||||
priv->n_out_buffers = priv->n_in_buffers;
|
||||
|
|
@ -321,7 +330,8 @@ do_allocation (PinosLink *this)
|
|||
in_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
|
||||
} else {
|
||||
g_warning ("error no common allocation found");
|
||||
return SPA_RESULT_ERROR;
|
||||
res = SPA_RESULT_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) {
|
||||
|
|
@ -329,7 +339,7 @@ do_allocation (PinosLink *this)
|
|||
oinfo->params, oinfo->n_params,
|
||||
priv->in_buffers, &priv->n_in_buffers)) < 0) {
|
||||
g_warning ("error alloc buffers: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
priv->input->n_buffers = priv->n_in_buffers;
|
||||
priv->input->buffers = priv->in_buffers;
|
||||
|
|
@ -339,7 +349,7 @@ do_allocation (PinosLink *this)
|
|||
iinfo->params, iinfo->n_params,
|
||||
priv->out_buffers, &priv->n_out_buffers)) < 0) {
|
||||
g_warning ("error alloc buffers: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
priv->output->n_buffers = priv->n_out_buffers;
|
||||
priv->output->buffers = priv->out_buffers;
|
||||
|
|
@ -348,7 +358,7 @@ do_allocation (PinosLink *this)
|
|||
if ((res = spa_node_port_use_buffers (priv->input_node, priv->input_port,
|
||||
priv->out_buffers, priv->n_out_buffers)) < 0) {
|
||||
g_warning ("error use buffers: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
priv->input->n_buffers = priv->n_out_buffers;
|
||||
priv->input->buffers = priv->out_buffers;
|
||||
|
|
@ -357,15 +367,19 @@ do_allocation (PinosLink *this)
|
|||
if ((res = spa_node_port_use_buffers (priv->output_node, priv->output_port,
|
||||
priv->in_buffers, priv->n_in_buffers)) < 0) {
|
||||
g_warning ("error use buffers: %d", res);
|
||||
return res;
|
||||
goto error;
|
||||
}
|
||||
priv->output->n_buffers = priv->n_in_buffers;
|
||||
priv->output->buffers = priv->in_buffers;
|
||||
}
|
||||
|
||||
priv->allocated = TRUE;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
error:
|
||||
{
|
||||
priv->allocated = FALSE;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -375,6 +389,8 @@ do_start (PinosLink *this)
|
|||
SpaCommand cmd;
|
||||
SpaResult res;
|
||||
|
||||
priv->started = TRUE;
|
||||
|
||||
cmd.type = SPA_COMMAND_START;
|
||||
if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0)
|
||||
g_warning ("got error %d", res);
|
||||
|
|
@ -391,6 +407,8 @@ do_pause (PinosLink *this)
|
|||
SpaCommand cmd;
|
||||
SpaResult res;
|
||||
|
||||
priv->started = FALSE;
|
||||
|
||||
cmd.type = SPA_COMMAND_PAUSE;
|
||||
if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0)
|
||||
g_warning ("got error %d", res);
|
||||
|
|
@ -408,18 +426,21 @@ check_states (PinosLink *this)
|
|||
|
||||
g_debug ("link %p: input %d, output %d", this, priv->input_state, priv->output_state);
|
||||
|
||||
if (priv->input_state == SPA_NODE_STATE_CONFIGURE &&
|
||||
priv->output_state == SPA_NODE_STATE_CONFIGURE &&
|
||||
if (priv->input_state >= SPA_NODE_STATE_CONFIGURE &&
|
||||
priv->output_state >= SPA_NODE_STATE_CONFIGURE &&
|
||||
!priv->negotiated) {
|
||||
if ((res = do_negotiate (this)) < 0)
|
||||
return res;
|
||||
}
|
||||
if (priv->input_state == SPA_NODE_STATE_READY &&
|
||||
priv->output_state == SPA_NODE_STATE_READY &&
|
||||
if (priv->input_state >= SPA_NODE_STATE_READY &&
|
||||
priv->output_state >= SPA_NODE_STATE_READY &&
|
||||
!priv->allocated) {
|
||||
if ((res = do_allocation (this)) < 0)
|
||||
return res;
|
||||
|
||||
}
|
||||
if (priv->input_state >= SPA_NODE_STATE_PAUSED &&
|
||||
priv->output_state >= SPA_NODE_STATE_PAUSED &&
|
||||
!priv->started) {
|
||||
if ((res = do_start (this)) < 0)
|
||||
return res;
|
||||
}
|
||||
|
|
@ -546,10 +567,15 @@ pinos_link_constructed (GObject * object)
|
|||
static void
|
||||
pinos_link_dispose (GObject * object)
|
||||
{
|
||||
PinosLink *link = PINOS_LINK (object);
|
||||
PinosLinkPrivate *priv = link->priv;
|
||||
PinosLink *this = PINOS_LINK (object);
|
||||
PinosLinkPrivate *priv = this->priv;
|
||||
|
||||
g_debug ("link %p: dispose", link);
|
||||
g_debug ("link %p: dispose", this);
|
||||
|
||||
g_signal_handlers_disconnect_by_data (priv->input, this);
|
||||
g_signal_handlers_disconnect_by_data (priv->output, this);
|
||||
g_signal_handlers_disconnect_by_data (priv->input->node, this);
|
||||
g_signal_handlers_disconnect_by_data (priv->output->node, this);
|
||||
|
||||
pinos_port_remove_send_cb (priv->input, priv->input_id);
|
||||
pinos_port_remove_send_cb (priv->output, priv->output_id);
|
||||
|
|
@ -560,7 +586,7 @@ pinos_link_dispose (GObject * object)
|
|||
}
|
||||
priv->input = NULL;
|
||||
priv->output = NULL;
|
||||
link_unregister_object (link);
|
||||
link_unregister_object (this);
|
||||
|
||||
G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ typedef enum {
|
|||
SPA_PROP_ID_AUDIO_RAW_INFO,
|
||||
} SpaPropIdAudio;
|
||||
|
||||
SpaResult spa_prop_info_fill_audio (SpaPropInfo *info,
|
||||
SpaPropIdAudio id,
|
||||
size_t offset);
|
||||
|
||||
struct _SpaAudioRawFormat {
|
||||
SpaFormat format;
|
||||
SpaAudioRawInfo info;
|
||||
|
|
@ -48,10 +52,6 @@ SpaResult spa_audio_raw_format_init (SpaAudioRawFormat *format);
|
|||
SpaResult spa_audio_raw_format_parse (const SpaFormat *format,
|
||||
SpaAudioRawFormat *rawformat);
|
||||
|
||||
SpaResult spa_audio_raw_fill_prop_info (SpaPropInfo *info,
|
||||
SpaPropIdAudio id,
|
||||
size_t offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -81,10 +81,9 @@ typedef enum {
|
|||
SPA_CONTROL_CMD_ADD_MEM = 64,
|
||||
SPA_CONTROL_CMD_REMOVE_MEM = 65,
|
||||
|
||||
SPA_CONTROL_CMD_ADD_BUFFER = 66,
|
||||
SPA_CONTROL_CMD_REMOVE_BUFFER = 67,
|
||||
SPA_CONTROL_CMD_PROCESS_BUFFER = 68,
|
||||
SPA_CONTROL_CMD_REUSE_BUFFER = 69,
|
||||
SPA_CONTROL_CMD_USE_BUFFERS = 66,
|
||||
SPA_CONTROL_CMD_PROCESS_BUFFER = 67,
|
||||
SPA_CONTROL_CMD_REUSE_BUFFER = 68,
|
||||
|
||||
} SpaControlCmd;
|
||||
|
||||
|
|
@ -184,18 +183,12 @@ typedef struct {
|
|||
SpaMemoryRef mem;
|
||||
} SpaControlCmdRemoveMem;
|
||||
|
||||
/* SPA_CONTROL_CMD_ADD_BUFFER */
|
||||
/* SPA_CONTROL_CMD_USE_BUFFERS */
|
||||
typedef struct {
|
||||
uint32_t port_id;
|
||||
uint32_t buffer_id;
|
||||
SpaMemoryChunk mem;
|
||||
} SpaControlCmdAddBuffer;
|
||||
|
||||
/* SPA_CONTROL_CMD_REMOVE_BUFFER */
|
||||
typedef struct {
|
||||
uint32_t port_id;
|
||||
uint32_t buffer_id;
|
||||
} SpaControlCmdRemoveBuffer;
|
||||
unsigned int n_buffers;
|
||||
SpaBuffer **buffers;
|
||||
} SpaControlCmdUseBuffers;
|
||||
|
||||
/* SPA_CONTROL_CMD_PROCESS_BUFFER */
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ typedef struct {
|
|||
/**
|
||||
* SpaPropInfo:
|
||||
* @id: unique id
|
||||
* @offset: offset in structure with data
|
||||
* @name: human readable name
|
||||
* @description: description of the property
|
||||
* @flags: property flags
|
||||
|
|
@ -123,10 +124,10 @@ typedef struct {
|
|||
* @n_range_values: number of elements in @range_values
|
||||
* @range_values: array of possible values
|
||||
* @tags: extra tags, NULL terminated
|
||||
* @offset: offset in structure with data
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
size_t offset;
|
||||
const char *name;
|
||||
const char *description;
|
||||
SpaPropFlags flags;
|
||||
|
|
@ -136,7 +137,6 @@ typedef struct {
|
|||
unsigned int n_range_values;
|
||||
const SpaPropRangeInfo *range_values;
|
||||
const char **tags;
|
||||
size_t offset;
|
||||
} SpaPropInfo;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
42
spa/include/spa/video/encoded.h
Normal file
42
spa/include/spa/video/encoded.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* Simple Plugin API
|
||||
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SPA_VIDEO_ENCODED_H__
|
||||
#define __SPA_VIDEO_ENCODED_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _SpaVideoInfoJPEG SpaVideoInfoJPEG;
|
||||
|
||||
#include <spa/format.h>
|
||||
#include <spa/video/format.h>
|
||||
|
||||
struct _SpaVideoInfoJPEG {
|
||||
SpaRectangle size;
|
||||
SpaFraction framerate;
|
||||
SpaFraction max_framerate;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __SPA_VIDEO_ENCODED_H__ */
|
||||
|
|
@ -26,8 +26,9 @@ extern "C" {
|
|||
|
||||
#include <spa/format.h>
|
||||
#include <spa/video/raw.h>
|
||||
#include <spa/video/encoded.h>
|
||||
|
||||
typedef struct _SpaVideoRawFormat SpaVideoRawFormat;
|
||||
typedef struct _SpaFormatVideo SpaFormatVideo;
|
||||
|
||||
typedef enum {
|
||||
SPA_PROP_ID_VIDEO_FORMAT = SPA_PROP_ID_MEDIA_CUSTOM_START,
|
||||
|
|
@ -47,20 +48,24 @@ typedef enum {
|
|||
SPA_PROP_ID_VIDEO_RAW_INFO,
|
||||
} SpaPropIdVideo;
|
||||
|
||||
struct _SpaVideoRawFormat {
|
||||
SpaFormat format;
|
||||
SpaVideoRawInfo info;
|
||||
};
|
||||
|
||||
SpaResult spa_video_raw_format_init (SpaVideoRawFormat *format);
|
||||
SpaResult spa_video_raw_format_parse (const SpaFormat *format,
|
||||
SpaVideoRawFormat *rawformat);
|
||||
|
||||
SpaResult spa_video_raw_fill_default_info (SpaVideoRawInfo *info);
|
||||
SpaResult spa_video_raw_fill_prop_info (SpaPropInfo *info,
|
||||
SpaResult spa_prop_info_fill_video (SpaPropInfo *info,
|
||||
SpaPropIdVideo id,
|
||||
size_t offset);
|
||||
|
||||
SpaResult spa_format_video_init (SpaMediaType type,
|
||||
SpaMediaSubType subtype,
|
||||
SpaFormatVideo *format);
|
||||
SpaResult spa_format_video_parse (const SpaFormat *format,
|
||||
SpaFormatVideo *dest);
|
||||
|
||||
struct _SpaFormatVideo {
|
||||
SpaFormat format;
|
||||
union {
|
||||
SpaVideoInfoRaw raw;
|
||||
SpaVideoInfoJPEG jpeg;
|
||||
} info;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _SpaVideoRawInfo SpaVideoRawInfo;
|
||||
typedef struct _SpaVideoInfoRaw SpaVideoInfoRaw;
|
||||
|
||||
#include <spa/props.h>
|
||||
#include <spa/video/chroma.h>
|
||||
|
|
@ -146,7 +146,7 @@ typedef enum {
|
|||
} SpaVideoInterlaceMode;
|
||||
|
||||
/**
|
||||
* SpaVideoRawInfo:
|
||||
* SpaVideoInfoRaw:
|
||||
* @format: the format
|
||||
* @size: the frame size of the video
|
||||
* @framerate: the framerate of the video 0/1 means variable rate
|
||||
|
|
@ -165,7 +165,7 @@ typedef enum {
|
|||
* @transfer_function: the transfer function. used to convert between R'G'B' and RGB
|
||||
* @color_primaries: color primaries. used to convert between R'G'B' and CIE XYZ
|
||||
*/
|
||||
struct _SpaVideoRawInfo {
|
||||
struct _SpaVideoInfoRaw {
|
||||
SpaVideoFormat format;
|
||||
SpaRectangle size;
|
||||
SpaFraction framerate;
|
||||
|
|
|
|||
|
|
@ -135,55 +135,95 @@ static const SpaPropRangeInfo uint32_range[] = {
|
|||
{ "max", "Maximum value", 4, &max_uint32 },
|
||||
};
|
||||
|
||||
static const SpaPropInfo raw_format_prop_info[] =
|
||||
static const SpaPropInfo format_prop_info[] =
|
||||
{
|
||||
{ SPA_PROP_ID_AUDIO_FORMAT, "format", "The media format",
|
||||
{ SPA_PROP_ID_AUDIO_FORMAT, 0,
|
||||
"format", "The media format",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_format_range), format_format_range,
|
||||
NULL,
|
||||
offsetof (SpaAudioRawFormat, info.format) },
|
||||
{ SPA_PROP_ID_AUDIO_FLAGS, "flags", "Sample Flags",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_FLAGS, 0,
|
||||
"flags", "Sample Flags",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (flags_range), flags_range,
|
||||
NULL,
|
||||
offsetof (SpaAudioRawFormat, info.flags) },
|
||||
{ SPA_PROP_ID_AUDIO_LAYOUT, "layout", "Sample Layout",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_LAYOUT, 0,
|
||||
"layout", "Sample Layout",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (layouts_range), layouts_range,
|
||||
NULL,
|
||||
offsetof (SpaAudioRawFormat, info.layout) },
|
||||
{ SPA_PROP_ID_AUDIO_RATE, "rate", "Audio sample rate",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_RATE, 0,
|
||||
"rate", "Audio sample rate",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||
NULL,
|
||||
offsetof (SpaAudioRawFormat, info.rate) },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNELS, "channels", "Audio channels",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNELS, 0,
|
||||
"channels", "Audio channels",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||
NULL,
|
||||
offsetof (SpaAudioRawFormat, info.channels) },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, "channel-mask", "Audio channel mask",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, 0,
|
||||
"channel-mask", "Audio channel mask",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_BITMASK, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaAudioRawFormat, info.channel_mask) },
|
||||
{ SPA_PROP_ID_AUDIO_RAW_INFO, "info", "the SpaAudioRawInfo structure",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_RAW_INFO, 0,
|
||||
"info", "the SpaAudioRawInfo structure",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_POINTER, sizeof (SpaAudioRawInfo),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaAudioRawFormat, info) },
|
||||
NULL },
|
||||
};
|
||||
|
||||
SpaResult
|
||||
spa_prop_info_fill_audio (SpaPropInfo *info,
|
||||
SpaPropIdAudio id,
|
||||
size_t offset)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (info == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
for (i = 0; i < SPA_N_ELEMENTS (format_prop_info); i++) {
|
||||
if (format_prop_info[i].id == id) {
|
||||
memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo));
|
||||
info->offset = offset;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_INVALID_PROPERTY_INDEX;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_audio_raw_format_init (SpaAudioRawFormat *format)
|
||||
{
|
||||
static SpaPropInfo raw_format_prop_info[] =
|
||||
{
|
||||
{ SPA_PROP_ID_AUDIO_FORMAT, offsetof (SpaAudioRawFormat, info.format), },
|
||||
{ SPA_PROP_ID_AUDIO_FLAGS, offsetof (SpaAudioRawFormat, info.flags), },
|
||||
{ SPA_PROP_ID_AUDIO_LAYOUT, offsetof (SpaAudioRawFormat, info.layout), },
|
||||
{ SPA_PROP_ID_AUDIO_RATE, offsetof (SpaAudioRawFormat, info.rate), },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNELS, offsetof (SpaAudioRawFormat, info.channels), },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, offsetof (SpaAudioRawFormat, info.channel_mask), },
|
||||
{ SPA_PROP_ID_AUDIO_RAW_INFO, offsetof (SpaAudioRawFormat, info), },
|
||||
};
|
||||
|
||||
if (raw_format_prop_info[0].name == NULL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++)
|
||||
spa_prop_info_fill_audio (&raw_format_prop_info[i],
|
||||
raw_format_prop_info[i].id,
|
||||
raw_format_prop_info[i].offset);
|
||||
}
|
||||
|
||||
format->format.media_type = SPA_MEDIA_TYPE_AUDIO;
|
||||
format->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW;
|
||||
format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
|
||||
|
|
@ -227,23 +267,3 @@ fallback:
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_audio_raw_fill_prop_info (SpaPropInfo *info,
|
||||
SpaPropIdAudio id,
|
||||
size_t offset)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (info == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++) {
|
||||
if (raw_format_prop_info[i].id == id) {
|
||||
memcpy (info, &raw_format_prop_info[i], sizeof (SpaPropInfo));
|
||||
info->offset = offset;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_INVALID_PROPERTY_INDEX;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -456,6 +456,27 @@ iter_parse_set_format (struct stack_iter *si, SpaControlCmdSetFormat *cmd)
|
|||
cmd->format = parse_format (mem, p, SPA_PTR_TO_INT (cmd->format));
|
||||
}
|
||||
|
||||
static void
|
||||
iter_parse_use_buffers (struct stack_iter *si, SpaControlCmdUseBuffers *cmd)
|
||||
{
|
||||
void *p;
|
||||
int i;
|
||||
|
||||
p = si->data;
|
||||
memcpy (cmd, p, sizeof (SpaControlCmdUseBuffers));
|
||||
if (cmd->buffers)
|
||||
cmd->buffers = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers), SpaBuffer *);
|
||||
for (i = 0; i < cmd->n_buffers; i++) {
|
||||
SpaMemoryChunk *mc;
|
||||
SpaMemory *mem;
|
||||
|
||||
mc = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers[i]), SpaMemoryChunk);
|
||||
mem = spa_memory_find (&mc->mem);
|
||||
|
||||
cmd->buffers[i] = SPA_MEMBER (spa_memory_ensure_ptr (mem), mc->offset, SpaBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_control_iter_parse_cmd (SpaControlIter *iter,
|
||||
void *command)
|
||||
|
|
@ -542,16 +563,8 @@ spa_control_iter_parse_cmd (SpaControlIter *iter,
|
|||
memcpy (command, si->data, sizeof (SpaControlCmdRemoveMem));
|
||||
break;
|
||||
|
||||
case SPA_CONTROL_CMD_ADD_BUFFER:
|
||||
if (si->size < sizeof (SpaControlCmdAddBuffer))
|
||||
return SPA_RESULT_ERROR;
|
||||
memcpy (command, si->data, sizeof (SpaControlCmdAddBuffer));
|
||||
break;
|
||||
|
||||
case SPA_CONTROL_CMD_REMOVE_BUFFER:
|
||||
if (si->size < sizeof (SpaControlCmdRemoveBuffer))
|
||||
return SPA_RESULT_ERROR;
|
||||
memcpy (command, si->data, sizeof (SpaControlCmdRemoveBuffer));
|
||||
case SPA_CONTROL_CMD_USE_BUFFERS:
|
||||
iter_parse_use_buffers (si, command);
|
||||
break;
|
||||
|
||||
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
||||
|
|
@ -1077,6 +1090,41 @@ builder_add_set_format (struct stack_builder *sb, SpaControlCmdSetFormat *sf)
|
|||
sf->format = SPA_INT_TO_PTR (SPA_PTRDIFF (p, sf));
|
||||
}
|
||||
|
||||
static void
|
||||
builder_add_use_buffers (struct stack_builder *sb, SpaControlCmdUseBuffers *ub)
|
||||
{
|
||||
size_t len;
|
||||
void *p;
|
||||
int i;
|
||||
SpaMemoryChunk **bmc;
|
||||
SpaControlCmdUseBuffers *d;
|
||||
|
||||
/* calculate length */
|
||||
/* port_id + format + mask */
|
||||
len = sizeof (SpaControlCmdUseBuffers);
|
||||
len += ub->n_buffers * sizeof (SpaBuffer *);
|
||||
len += ub->n_buffers * sizeof (SpaMemoryChunk);
|
||||
|
||||
p = builder_add_cmd (sb, SPA_CONTROL_CMD_USE_BUFFERS, len);
|
||||
memcpy (p, ub, sizeof (SpaControlCmdUseBuffers));
|
||||
d = p;
|
||||
|
||||
p = SPA_MEMBER (d, sizeof (SpaControlCmdUseBuffers), void);
|
||||
bmc = p;
|
||||
|
||||
if (d->n_buffers)
|
||||
d->buffers = SPA_INT_TO_PTR (SPA_PTRDIFF (bmc, d));
|
||||
else
|
||||
d->buffers = 0;
|
||||
|
||||
p = SPA_MEMBER (p, sizeof (SpaMemoryChunk*) * ub->n_buffers, void);
|
||||
for (i = 0; i < ub->n_buffers; i++) {
|
||||
memcpy (p, &ub->buffers[i]->mem, sizeof (SpaMemoryChunk));
|
||||
bmc[i] = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
|
||||
p = SPA_MEMBER (p, sizeof (SpaMemoryChunk), void);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* spa_control_builder_add_cmd:
|
||||
* @builder: a #SpaControlBuilder
|
||||
|
|
@ -1168,14 +1216,8 @@ spa_control_builder_add_cmd (SpaControlBuilder *builder,
|
|||
memcpy (p, command, sizeof (SpaControlCmdRemoveMem));
|
||||
break;
|
||||
|
||||
case SPA_CONTROL_CMD_ADD_BUFFER:
|
||||
p = builder_add_cmd (sb, cmd, sizeof (SpaControlCmdAddBuffer));
|
||||
memcpy (p, command, sizeof (SpaControlCmdAddBuffer));
|
||||
break;
|
||||
|
||||
case SPA_CONTROL_CMD_REMOVE_BUFFER:
|
||||
p = builder_add_cmd (sb, cmd, sizeof (SpaControlCmdRemoveBuffer));
|
||||
memcpy (p, command, sizeof (SpaControlCmdRemoveBuffer));
|
||||
case SPA_CONTROL_CMD_USE_BUFFERS:
|
||||
builder_add_use_buffers (sb, command);
|
||||
break;
|
||||
|
||||
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
||||
|
|
|
|||
|
|
@ -169,18 +169,31 @@ spa_debug_dump_mem (const void *mem, size_t size)
|
|||
struct media_type_name {
|
||||
const char *name;
|
||||
} media_type_names[] = {
|
||||
{ "unknown" },
|
||||
{ "invalid" },
|
||||
{ "audio" },
|
||||
{ "video" },
|
||||
{ "image" },
|
||||
};
|
||||
|
||||
struct media_subtype_name {
|
||||
const char *name;
|
||||
} media_subtype_names[] = {
|
||||
{ "unknown" },
|
||||
{ "invalid" },
|
||||
{ "raw" },
|
||||
{ "h264" },
|
||||
{ "mjpg" },
|
||||
{ "dv" },
|
||||
{ "mpegts" },
|
||||
{ "h263" },
|
||||
{ "mpeg1" },
|
||||
{ "mpeg2" },
|
||||
{ "mpeg4" },
|
||||
{ "xvid" },
|
||||
{ "vc1" },
|
||||
{ "vp8" },
|
||||
{ "vp9" },
|
||||
{ "jpeg" },
|
||||
{ "bayer" },
|
||||
};
|
||||
|
||||
struct prop_type_name {
|
||||
|
|
@ -330,7 +343,7 @@ spa_debug_props (const SpaProps *props, bool print_ranges)
|
|||
|
||||
res = spa_props_get_prop (props, i, &value);
|
||||
|
||||
fprintf (stderr, ". Current: ");
|
||||
fprintf (stderr, "Current: ");
|
||||
if (res == SPA_RESULT_OK)
|
||||
print_value (info, value.size, value.value);
|
||||
else if (res == SPA_RESULT_PROPERTY_UNSET)
|
||||
|
|
@ -386,14 +399,25 @@ spa_debug_format (const SpaFormat *format)
|
|||
{
|
||||
const SpaProps *props;
|
||||
int i;
|
||||
const char *media_type;
|
||||
const char *media_subtype;
|
||||
|
||||
if (format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
props = &format->props;
|
||||
|
||||
fprintf (stderr, "%-6s %s/%s\n", "", media_type_names[format->media_type].name,
|
||||
media_subtype_names[format->media_subtype].name);
|
||||
if (format->media_type > 0 && format->media_type < SPA_N_ELEMENTS (media_type_names))
|
||||
media_type = media_type_names[format->media_type].name;
|
||||
else
|
||||
media_type = "unknown";
|
||||
|
||||
if (format->media_subtype > 0 && format->media_subtype < SPA_N_ELEMENTS (media_subtype_names))
|
||||
media_subtype = media_subtype_names[format->media_subtype].name;
|
||||
else
|
||||
media_subtype = "unknown";
|
||||
|
||||
fprintf (stderr, "%-6s %s/%s\n", "", media_type, media_subtype);
|
||||
|
||||
for (i = 0; i < props->n_prop_info; i++) {
|
||||
const SpaPropInfo *info = &props->prop_info[i];
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include <spa/video/raw.h>
|
||||
#include <spa/video/format.h>
|
||||
|
||||
static const SpaVideoRawInfo default_info = {
|
||||
static const SpaVideoInfoRaw default_raw_info = {
|
||||
SPA_VIDEO_FORMAT_UNKNOWN,
|
||||
{ 320, 240 },
|
||||
{ 0, 1 },
|
||||
|
|
@ -371,175 +371,193 @@ static const SpaPropRangeInfo framerate_range[] = {
|
|||
{ "max", "Maximum value", sizeof (SpaFraction), &max_framerate },
|
||||
};
|
||||
|
||||
static const SpaPropInfo raw_format_prop_info[] =
|
||||
static const SpaPropInfo format_prop_info[] =
|
||||
{
|
||||
{ SPA_PROP_ID_VIDEO_FORMAT, "format", "The media format",
|
||||
{ SPA_PROP_ID_VIDEO_FORMAT, 0,
|
||||
"format", "The media format",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_range), format_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.format) },
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, "size", "Video size",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, 0,
|
||||
"size", "Video size",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_RECTANGLE, sizeof (SpaRectangle),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, size_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.size) },
|
||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, "framerate", "Video framerate",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, 0,
|
||||
"framerate", "Video framerate",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, "max-framerate", "Video max framerate",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, 0,
|
||||
"max-framerate", "Video max framerate",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.max_framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_VIEWS, "views", "Video number of views",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_VIEWS, 0,
|
||||
"views", "Video number of views",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.views) },
|
||||
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, "interlace-mode", "Interlace mode",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, 0,
|
||||
"interlace-mode", "Interlace mode",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (interlace_mode_range), interlace_mode_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.interlace_mode) },
|
||||
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, "pixel-aspect-ratio", "Video pixel aspect ratio",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, 0,
|
||||
"pixel-aspect-ratio", "Video pixel aspect ratio",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.pixel_aspect_ratio) },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, "multiview-mode", "Multiview mode",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, 0,
|
||||
"multiview-mode", "Multiview mode",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (multiview_mode_range), multiview_mode_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.multiview_mode) },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, "multiview-flags", "Multiview flags",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, 0,
|
||||
"multiview-flags", "Multiview flags",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (multiview_flags_range), multiview_flags_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.multiview_flags) },
|
||||
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, "chroma-site", "Chroma site",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, 0,
|
||||
"chroma-site", "Chroma site",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (chroma_site_range), chroma_site_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.chroma_site) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, "color-range", "Color range",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, 0,
|
||||
"color-range", "Color range",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_range_range), color_range_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.color_range) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, "color-matrix", "Color matrix",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, 0,
|
||||
"color-matrix", "Color matrix",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_matrix_range), color_matrix_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.color_matrix) },
|
||||
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, "transfer-function", "Transfer function",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, 0,
|
||||
"transfer-function", "Transfer function",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (transfer_function_range), transfer_function_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.transfer_function) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, "color-primaries", "Color primaries",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, 0,
|
||||
"color-primaries", "Color primaries",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_primaries_range), color_primaries_range,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info.color_primaries) },
|
||||
{ SPA_PROP_ID_VIDEO_RAW_INFO, "info", "the SpaVideoRawInfo structure",
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_RAW_INFO, 0,
|
||||
"info", "the SpaVideoRawInfo structure",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_POINTER, sizeof (SpaVideoRawInfo),
|
||||
SPA_PROP_TYPE_POINTER, sizeof (SpaVideoInfoRaw),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaVideoRawFormat, info) },
|
||||
NULL },
|
||||
};
|
||||
|
||||
SpaResult
|
||||
spa_video_raw_format_init (SpaVideoRawFormat *format)
|
||||
spa_prop_info_fill_video (SpaPropInfo *info,
|
||||
SpaPropIdVideo id,
|
||||
size_t offset)
|
||||
{
|
||||
format->format.media_type = SPA_MEDIA_TYPE_VIDEO;
|
||||
format->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW;
|
||||
format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
|
||||
format->format.props.prop_info = raw_format_prop_info;
|
||||
format->format.props.unset_mask = (1 << 14)-1;
|
||||
format->info = default_info;
|
||||
int i;
|
||||
|
||||
if (info == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
i = id - SPA_PROP_ID_MEDIA_CUSTOM_START;
|
||||
|
||||
if (i < 0 || i >= SPA_N_ELEMENTS (format_prop_info))
|
||||
return SPA_RESULT_INVALID_PROPERTY_INDEX;
|
||||
|
||||
memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo));
|
||||
info->offset = offset;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_video_raw_format_parse (const SpaFormat *format,
|
||||
SpaVideoRawFormat *rawformat)
|
||||
spa_format_video_init (SpaMediaType type,
|
||||
SpaMediaSubType subtype,
|
||||
SpaFormatVideo *format)
|
||||
{
|
||||
static SpaPropInfo raw_format_prop_info[] = {
|
||||
{ SPA_PROP_ID_VIDEO_FORMAT, offsetof (SpaFormatVideo, info.raw.format) },
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, offsetof (SpaFormatVideo, info.raw.size) },
|
||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, offsetof (SpaFormatVideo, info.raw.framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, offsetof (SpaFormatVideo, info.raw.max_framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_VIEWS, offsetof (SpaFormatVideo, info.raw.views) },
|
||||
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, offsetof (SpaFormatVideo, info.raw.interlace_mode) },
|
||||
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, offsetof (SpaFormatVideo, info.raw.pixel_aspect_ratio) },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, offsetof (SpaFormatVideo, info.raw.multiview_mode) },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, offsetof (SpaFormatVideo, info.raw.multiview_flags) },
|
||||
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, offsetof (SpaFormatVideo, info.raw.chroma_site) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, offsetof (SpaFormatVideo, info.raw.color_range) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, offsetof (SpaFormatVideo, info.raw.color_matrix) },
|
||||
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, offsetof (SpaFormatVideo, info.raw.transfer_function) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, offsetof (SpaFormatVideo, info.raw.color_primaries) },
|
||||
{ SPA_PROP_ID_VIDEO_RAW_INFO, offsetof (SpaFormatVideo, info.raw ) },
|
||||
};
|
||||
|
||||
if (raw_format_prop_info[0].name == NULL) {
|
||||
int i;
|
||||
for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++)
|
||||
spa_prop_info_fill_video (&raw_format_prop_info[i],
|
||||
raw_format_prop_info[i].id,
|
||||
raw_format_prop_info[i].offset);
|
||||
}
|
||||
|
||||
format->format.media_type = type;
|
||||
format->format.media_subtype = subtype;
|
||||
format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
|
||||
format->format.props.prop_info = raw_format_prop_info;
|
||||
format->format.props.unset_mask = (1 << 14)-1;
|
||||
format->info.raw = default_raw_info;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_video_parse (const SpaFormat *format,
|
||||
SpaFormatVideo *vformat)
|
||||
{
|
||||
SpaPropValue value;
|
||||
const SpaProps *props;
|
||||
SpaResult res;
|
||||
|
||||
if ((void *)format == (void *)rawformat)
|
||||
if ((void *)format == (void *)vformat)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
if (format->media_type != SPA_MEDIA_TYPE_VIDEO ||
|
||||
format->media_subtype != SPA_MEDIA_SUBTYPE_RAW)
|
||||
if (format->media_type != SPA_MEDIA_TYPE_VIDEO)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
spa_video_raw_format_init (rawformat);
|
||||
spa_format_video_init (format->media_type,
|
||||
format->media_subtype,
|
||||
vformat);
|
||||
|
||||
props = &format->props;
|
||||
if ((res = spa_props_get_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_RAW_INFO), &value)) < 0)
|
||||
goto fallback;
|
||||
|
||||
if (value.type != SPA_PROP_TYPE_POINTER || value.size != sizeof (SpaVideoRawInfo))
|
||||
if (value.type != SPA_PROP_TYPE_POINTER)
|
||||
goto fallback;
|
||||
|
||||
memcpy (&rawformat->info, value.value, sizeof (SpaVideoRawInfo));
|
||||
memcpy (&vformat->info, value.value, value.size);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
fallback:
|
||||
res = spa_props_copy (props, &rawformat->format.props);
|
||||
res = spa_props_copy (props, &vformat->format.props);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_video_raw_fill_default_info (SpaVideoRawInfo *info)
|
||||
{
|
||||
if (info == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
memcpy (info, &default_info, sizeof (SpaVideoRawInfo));
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
SpaResult
|
||||
spa_video_raw_fill_prop_info (SpaPropInfo *info,
|
||||
SpaPropIdVideo id,
|
||||
size_t offset)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (info == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++) {
|
||||
if (raw_format_prop_info[i].id == id) {
|
||||
memcpy (info, &raw_format_prop_info[i], sizeof (SpaPropInfo));
|
||||
info->offset = offset;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_INVALID_PROPERTY_INDEX;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,42 +123,42 @@ enum {
|
|||
|
||||
static const SpaPropInfo prop_info[] =
|
||||
{
|
||||
{ PROP_ID_DEVICE, "device", "ALSA device, as defined in an asound configuration file",
|
||||
{ PROP_ID_DEVICE, offsetof (SpaALSASinkProps, device),
|
||||
"device", "ALSA device, as defined in an asound configuration file",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_STRING, 63,
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaALSASinkProps, device) },
|
||||
{ PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the sound device",
|
||||
NULL },
|
||||
{ PROP_ID_DEVICE_NAME, offsetof (SpaALSASinkProps, device_name),
|
||||
"device-name", "Human-readable name of the sound device",
|
||||
SPA_PROP_FLAG_READABLE,
|
||||
SPA_PROP_TYPE_STRING, 127,
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaALSASinkProps, device_name) },
|
||||
{ PROP_ID_CARD_NAME, "card-name", "Human-readable name of the sound card",
|
||||
NULL },
|
||||
{ PROP_ID_CARD_NAME, offsetof (SpaALSASinkProps, card_name),
|
||||
"card-name", "Human-readable name of the sound card",
|
||||
SPA_PROP_FLAG_READABLE,
|
||||
SPA_PROP_TYPE_STRING, 127,
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaALSASinkProps, card_name) },
|
||||
{ PROP_ID_BUFFER_TIME, "buffer-time", "The total size of the buffer in time",
|
||||
NULL },
|
||||
{ PROP_ID_BUFFER_TIME, offsetof (SpaALSASinkProps, buffer_time),
|
||||
"buffer-time", "The total size of the buffer in time",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||
NULL,
|
||||
offsetof (SpaALSASinkProps, buffer_time) },
|
||||
{ PROP_ID_PERIOD_TIME, "period-time", "The size of a period in time",
|
||||
NULL },
|
||||
{ PROP_ID_PERIOD_TIME, offsetof (SpaALSASinkProps, period_time),
|
||||
"period-time", "The size of a period in time",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||
NULL,
|
||||
offsetof (SpaALSASinkProps, period_time) },
|
||||
{ PROP_ID_PERIOD_EVENT, "period-event", "Generate an event each period",
|
||||
NULL },
|
||||
{ PROP_ID_PERIOD_EVENT, offsetof (SpaALSASinkProps, period_event),
|
||||
"period-event", "Generate an event each period",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_BOOL, sizeof (bool),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaALSASinkProps, period_event) },
|
||||
NULL },
|
||||
};
|
||||
|
||||
static SpaResult
|
||||
|
|
|
|||
|
|
@ -84,24 +84,24 @@ enum {
|
|||
|
||||
static const SpaPropInfo prop_info[] =
|
||||
{
|
||||
{ PROP_ID_WAVE, "wave", "Oscillator waveform",
|
||||
{ PROP_ID_WAVE, offsetof (SpaAudioTestSrcProps, wave),
|
||||
"wave", "Oscillator waveform",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (wave_range), wave_range,
|
||||
NULL,
|
||||
offsetof (SpaAudioTestSrcProps, wave) },
|
||||
{ PROP_ID_FREQ, "freq", "Frequency of test signal. The sample rate needs to be at least 4 times higher",
|
||||
NULL },
|
||||
{ PROP_ID_FREQ, offsetof (SpaAudioTestSrcProps, freq),
|
||||
"freq", "Frequency of test signal. The sample rate needs to be at least 4 times higher",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, freq_range,
|
||||
NULL,
|
||||
offsetof (SpaAudioTestSrcProps, freq) },
|
||||
{ PROP_ID_VOLUME, "volume", "The Volume factor",
|
||||
NULL },
|
||||
{ PROP_ID_VOLUME, offsetof (SpaAudioTestSrcProps, volume),
|
||||
"volume", "The Volume factor",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range,
|
||||
NULL,
|
||||
offsetof (SpaAudioTestSrcProps, volume) },
|
||||
NULL },
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -465,7 +465,7 @@ spa_audiotestsrc_node_port_pull_output (SpaNode *node,
|
|||
{
|
||||
SpaAudioTestSrc *this;
|
||||
size_t j, size;
|
||||
uint8_t *ptr;
|
||||
uint8_t *ptr = NULL;
|
||||
unsigned int i;
|
||||
bool have_error = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ struct _FFMpegBuffer {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
SpaVideoRawFormat raw_format[2];
|
||||
SpaFormatVideo format[2];
|
||||
SpaFormat *current_format;
|
||||
bool have_buffers;
|
||||
FFMpegBuffer buffers[MAX_BUFFERS];
|
||||
|
|
@ -278,12 +278,14 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_video_raw_format_init (&s->raw_format[0]);
|
||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&s->format[0]);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &s->raw_format[0].format;
|
||||
*format = &s->format[0].format;
|
||||
*(int*)state = ++index;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -298,8 +300,6 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
|
|||
SpaFFMpegDec *this;
|
||||
SpaFFMpegState *state;
|
||||
SpaResult res;
|
||||
SpaFormat *f, *tf;
|
||||
size_t fs;
|
||||
|
||||
if (node == NULL || node->handle == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -316,22 +316,12 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
|
|||
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))
|
||||
if ((res = spa_format_video_parse (format, &state->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 (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||
memcpy (tf, f, fs);
|
||||
state->current_format = tf;
|
||||
memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo));
|
||||
state->current_format = &state->format[1].format;
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ struct _FFMpegBuffer {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
SpaVideoRawFormat raw_format[2];
|
||||
SpaFormatVideo format[2];
|
||||
SpaFormat *current_format;
|
||||
bool have_buffers;
|
||||
FFMpegBuffer buffers[MAX_BUFFERS];
|
||||
|
|
@ -278,12 +278,14 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_video_raw_format_init (&s->raw_format[0]);
|
||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&s->format[0]);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &s->raw_format[0].format;
|
||||
*format = &s->format[0].format;
|
||||
*(int*)state = ++index;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -298,8 +300,6 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
|
|||
SpaFFMpegEnc *this;
|
||||
SpaFFMpegState *state;
|
||||
SpaResult res;
|
||||
SpaFormat *f, *tf;
|
||||
size_t fs;
|
||||
|
||||
if (node == NULL || node->handle == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -315,23 +315,16 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
|
|||
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))
|
||||
if ((res = spa_format_video_parse (format, &state->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
|
||||
if (format->media_type != SPA_MEDIA_TYPE_VIDEO ||
|
||||
format->media_subtype != SPA_MEDIA_SUBTYPE_RAW)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||
memcpy (tf, f, fs);
|
||||
state->current_format = tf;
|
||||
memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo));
|
||||
state->current_format = &state->format[1].format;
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
|
|||
|
|
@ -88,12 +88,12 @@ enum {
|
|||
|
||||
static const SpaPropInfo prop_info[PROP_ID_LAST] =
|
||||
{
|
||||
{ PROP_ID_SOCKET, "socket", "The Socket factor",
|
||||
{ PROP_ID_SOCKET, offsetof (SpaProxyProps, socketfd),
|
||||
"socket", "The Socket factor",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_INT, sizeof (int),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaProxyProps, socketfd) },
|
||||
NULL },
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -626,10 +626,9 @@ spa_proxy_node_port_get_status (SpaNode *node,
|
|||
}
|
||||
|
||||
static SpaResult
|
||||
add_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuffer *buffer)
|
||||
add_buffer_mem (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuffer *buffer)
|
||||
{
|
||||
SpaControlCmdAddMem am;
|
||||
SpaControlCmdAddBuffer ab;
|
||||
int i;
|
||||
SpaBuffer *b;
|
||||
SpaMemory *bmem;
|
||||
|
|
@ -661,6 +660,10 @@ add_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuf
|
|||
fprintf (stderr, "proxy %p: error invalid memory\n", this);
|
||||
continue;
|
||||
}
|
||||
if (mem->fd == -1) {
|
||||
fprintf (stderr, "proxy %p: error memory without fd\n", this);
|
||||
continue;
|
||||
}
|
||||
|
||||
am.port_id = port_id;
|
||||
am.mem = mem->mem;
|
||||
|
|
@ -670,42 +673,10 @@ add_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuf
|
|||
am.size = mem->size;
|
||||
spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_ADD_MEM, &am);
|
||||
}
|
||||
ab.port_id = port_id;
|
||||
ab.buffer_id = b->id;
|
||||
ab.mem.mem = bmem->mem;
|
||||
ab.mem.offset = b->mem.offset;
|
||||
ab.mem.size = b->mem.size;
|
||||
spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
remove_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuffer *buffer)
|
||||
{
|
||||
SpaControlCmdRemoveBuffer rb;
|
||||
SpaControlCmdRemoveMem rm;
|
||||
unsigned int i;
|
||||
|
||||
rb.port_id = port_id;
|
||||
rb.buffer_id = buffer->id;
|
||||
spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_REMOVE_BUFFER, &rb);
|
||||
rm.port_id = port_id;
|
||||
rm.mem = buffer->mem.mem;
|
||||
spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_REMOVE_MEM, &rm);
|
||||
|
||||
for (i = 0; i < buffer->n_datas; i++) {
|
||||
SpaData *d = &SPA_BUFFER_DATAS (buffer)[i];
|
||||
|
||||
rm.port_id = port_id;
|
||||
rm.mem = d->mem.mem;
|
||||
spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_REMOVE_MEM, &rm);
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
static SpaResult
|
||||
spa_proxy_node_port_use_buffers (SpaNode *node,
|
||||
uint32_t port_id,
|
||||
|
|
@ -720,6 +691,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
|||
uint8_t buf[4096];
|
||||
int fds[32];
|
||||
SpaResult res;
|
||||
SpaControlCmdUseBuffers ub;
|
||||
|
||||
if (node == NULL || node->handle == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -737,9 +709,6 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
|||
|
||||
spa_control_builder_init_into (&builder, buf, sizeof (buf), fds, sizeof (fds));
|
||||
|
||||
for (i = 0; i < port->n_buffers; i++)
|
||||
remove_buffer (this, &builder, port_id, port->buffers[i]);
|
||||
|
||||
if (buffers == NULL || n_buffers == 0) {
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
|
|
@ -748,7 +717,12 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
|||
port->n_buffers = n_buffers;
|
||||
}
|
||||
for (i = 0; i < port->n_buffers; i++)
|
||||
add_buffer (this, &builder, port_id, port->buffers[i]);
|
||||
add_buffer_mem (this, &builder, port_id, port->buffers[i]);
|
||||
|
||||
ub.port_id = port_id;
|
||||
ub.n_buffers = port->n_buffers;
|
||||
ub.buffers = port->buffers;
|
||||
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_USE_BUFFERS, &ub);
|
||||
|
||||
spa_control_builder_end (&builder, &control);
|
||||
|
||||
|
|
@ -1044,9 +1018,7 @@ parse_control (SpaProxy *this,
|
|||
break;
|
||||
case SPA_CONTROL_CMD_REMOVE_MEM:
|
||||
break;
|
||||
case SPA_CONTROL_CMD_ADD_BUFFER:
|
||||
break;
|
||||
case SPA_CONTROL_CMD_REMOVE_BUFFER:
|
||||
case SPA_CONTROL_CMD_USE_BUFFERS:
|
||||
break;
|
||||
|
||||
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
||||
|
|
|
|||
|
|
@ -140,24 +140,24 @@ enum {
|
|||
|
||||
static const SpaPropInfo prop_info[] =
|
||||
{
|
||||
{ PROP_ID_DEVICE, "device", "V4l2 device location",
|
||||
{ PROP_ID_DEVICE, offsetof (SpaV4l2SourceProps, device),
|
||||
"device", "V4l2 device location",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_STRING, 63,
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaV4l2SourceProps, device) },
|
||||
{ PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the device",
|
||||
NULL },
|
||||
{ PROP_ID_DEVICE_NAME, offsetof (SpaV4l2SourceProps, device_name),
|
||||
"device-name", "Human-readable name of the device",
|
||||
SPA_PROP_FLAG_READABLE,
|
||||
SPA_PROP_TYPE_STRING, 127,
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaV4l2SourceProps, device_name) },
|
||||
{ PROP_ID_DEVICE_FD, "device-fd", "Device file descriptor",
|
||||
NULL },
|
||||
{ PROP_ID_DEVICE_FD, offsetof (SpaV4l2SourceProps, device_fd),
|
||||
"device-fd", "Device file descriptor",
|
||||
SPA_PROP_FLAG_READABLE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaV4l2SourceProps, device_fd) },
|
||||
NULL },
|
||||
};
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -357,13 +357,13 @@ spa_v4l2_format_init (V4l2Format *f)
|
|||
f->fmt.props.n_prop_info = 3;
|
||||
f->fmt.props.prop_info = f->infos;
|
||||
|
||||
spa_video_raw_fill_prop_info (&f->infos[0],
|
||||
spa_prop_info_fill_video (&f->infos[0],
|
||||
SPA_PROP_ID_VIDEO_FORMAT,
|
||||
offsetof (V4l2Format, format));
|
||||
spa_video_raw_fill_prop_info (&f->infos[1],
|
||||
spa_prop_info_fill_video (&f->infos[1],
|
||||
SPA_PROP_ID_VIDEO_SIZE,
|
||||
offsetof (V4l2Format, size));
|
||||
spa_video_raw_fill_prop_info (&f->infos[2],
|
||||
spa_prop_info_fill_video (&f->infos[2],
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||
offsetof (V4l2Format, framerate));
|
||||
}
|
||||
|
|
@ -386,7 +386,7 @@ spa_v4l2_source_node_port_enum_formats (SpaNode *node,
|
|||
if (port_id != 0)
|
||||
return SPA_RESULT_INVALID_PORT;
|
||||
|
||||
res = spa_v4l2_enum_format (this, format, state);
|
||||
res = spa_v4l2_enum_format (this, format, filter, state);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -403,7 +403,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
|
|||
V4l2Format *f, *tf;
|
||||
size_t fs;
|
||||
|
||||
if (node == NULL || node->handle == NULL || format == NULL)
|
||||
if (node == NULL || node->handle == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
this = (SpaV4l2Source *) node->handle;
|
||||
|
|
@ -417,6 +417,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
|
|||
spa_v4l2_clear_buffers (this);
|
||||
spa_v4l2_close (this);
|
||||
state->current_format = NULL;
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -280,15 +280,33 @@ video_format_to_format_info (SpaVideoFormat format)
|
|||
}
|
||||
#endif
|
||||
|
||||
static const FormatInfo *
|
||||
find_format_info_by_media_type (SpaMediaType type,
|
||||
SpaMediaSubType subtype,
|
||||
SpaVideoFormat format,
|
||||
int startidx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = startidx; i < SPA_N_ELEMENTS (format_info); i++) {
|
||||
if ((format_info[i].media_type == type) &&
|
||||
(format_info[i].media_subtype == subtype) &&
|
||||
(format == SPA_VIDEO_FORMAT_UNKNOWN || format_info[i].format == format))
|
||||
return &format_info[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define FOURCC_ARGS(f) (f)&0x7f,((f)>>8)&0x7f,((f)>>16)&0x7f,((f)>>24)&0x7f
|
||||
|
||||
static SpaResult
|
||||
spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, void **cookie)
|
||||
spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, const SpaFormat *filter, void **cookie)
|
||||
{
|
||||
SpaV4l2State *state = &this->state[0];
|
||||
int res, i, pi;
|
||||
V4l2Format *fmt;
|
||||
const FormatInfo *info;
|
||||
SpaVideoFormat video_format;
|
||||
|
||||
if (spa_v4l2_open (this) < 0)
|
||||
return SPA_RESULT_ERROR;
|
||||
|
|
@ -306,15 +324,47 @@ spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, void **cookie)
|
|||
*cookie = state;
|
||||
}
|
||||
|
||||
|
||||
again:
|
||||
if (state->next_fmtdesc) {
|
||||
if (filter) {
|
||||
SpaPropValue val;
|
||||
|
||||
if (state->fmtdesc.index == 1)
|
||||
return SPA_RESULT_ENUM_END;
|
||||
|
||||
video_format = SPA_VIDEO_FORMAT_UNKNOWN;
|
||||
if ((filter->media_type == SPA_MEDIA_TYPE_VIDEO)) {
|
||||
if (filter->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
||||
if (spa_props_get_prop (&filter->props,
|
||||
spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FORMAT),
|
||||
&val) >= 0) {
|
||||
video_format = *((SpaVideoFormat *)val.value);
|
||||
}
|
||||
} else {
|
||||
video_format = SPA_VIDEO_FORMAT_ENCODED;
|
||||
}
|
||||
} else if ((filter->media_type == SPA_MEDIA_TYPE_IMAGE)) {
|
||||
video_format = SPA_VIDEO_FORMAT_ENCODED;
|
||||
} else
|
||||
return SPA_RESULT_ENUM_END;
|
||||
|
||||
info = find_format_info_by_media_type (filter->media_type,
|
||||
filter->media_subtype,
|
||||
video_format,
|
||||
0);
|
||||
if (info == NULL)
|
||||
return SPA_RESULT_ENUM_END;
|
||||
|
||||
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;
|
||||
|
|
@ -354,21 +404,21 @@ again:
|
|||
fmt->fmt.props.unset_mask = 0;
|
||||
|
||||
if (info->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
||||
spa_video_raw_fill_prop_info (&fmt->infos[pi],
|
||||
spa_prop_info_fill_video (&fmt->infos[pi],
|
||||
SPA_PROP_ID_VIDEO_FORMAT,
|
||||
offsetof (V4l2Format, format));
|
||||
fmt->format = info->format;
|
||||
pi = ++fmt->fmt.props.n_prop_info;
|
||||
}
|
||||
|
||||
spa_video_raw_fill_prop_info (&fmt->infos[pi],
|
||||
spa_prop_info_fill_video (&fmt->infos[pi],
|
||||
SPA_PROP_ID_VIDEO_SIZE,
|
||||
offsetof (V4l2Format, size));
|
||||
fmt->size.width = state->frmsize.discrete.width;
|
||||
fmt->size.height = state->frmsize.discrete.height;
|
||||
pi = ++fmt->fmt.props.n_prop_info;
|
||||
|
||||
spa_video_raw_fill_prop_info (&fmt->infos[pi],
|
||||
spa_prop_info_fill_video (&fmt->infos[pi],
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||
offsetof (V4l2Format, framerate));
|
||||
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
|
||||
|
|
@ -417,21 +467,16 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
|
|||
struct v4l2_format reqfmt, fmt;
|
||||
struct v4l2_streamparm streamparm;
|
||||
const FormatInfo *info = NULL;
|
||||
int i;
|
||||
|
||||
CLEAR (fmt);
|
||||
CLEAR (streamparm);
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
for (i = 0; i < SPA_N_ELEMENTS (format_info); i++) {
|
||||
if (format_info[i].media_type == f->fmt.media_type &&
|
||||
format_info[i].media_subtype == f->fmt.media_subtype &&
|
||||
format_info[i].format == f->format) {
|
||||
info = &format_info[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
info = find_format_info_by_media_type (f->fmt.media_type,
|
||||
f->fmt.media_subtype,
|
||||
f->format,
|
||||
0);
|
||||
if (info == NULL)
|
||||
return -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -75,18 +75,18 @@ enum {
|
|||
|
||||
static const SpaPropInfo prop_info[] =
|
||||
{
|
||||
{ PROP_ID_VOLUME, "volume", "The Volume factor",
|
||||
{ PROP_ID_VOLUME, offsetof (SpaVolumeProps, volume),
|
||||
"volume", "The Volume factor",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range,
|
||||
NULL,
|
||||
offsetof (SpaVolumeProps, volume) },
|
||||
{ PROP_ID_MUTE, "mute", "Mute",
|
||||
NULL },
|
||||
{ PROP_ID_MUTE, offsetof (SpaVolumeProps, mute),
|
||||
"mute", "Mute",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_BOOL, sizeof (bool),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaVolumeProps, mute) },
|
||||
NULL },
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ struct _SpaXvSink {
|
|||
SpaEventCallback event_cb;
|
||||
void *user_data;
|
||||
|
||||
SpaVideoRawFormat raw_format[2];
|
||||
SpaFormatVideo format[2];
|
||||
SpaFormat *current_format;
|
||||
|
||||
SpaXvState state;
|
||||
|
|
@ -97,24 +97,24 @@ enum {
|
|||
|
||||
static const SpaPropInfo prop_info[] =
|
||||
{
|
||||
{ PROP_ID_DEVICE, "device", "Xv device location",
|
||||
{ PROP_ID_DEVICE, offsetof (SpaXvSinkProps, device),
|
||||
"device", "Xv device location",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_STRING, 63,
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaXvSinkProps, device) },
|
||||
{ PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the device",
|
||||
NULL },
|
||||
{ PROP_ID_DEVICE_NAME, offsetof (SpaXvSinkProps, device_name),
|
||||
"device-name", "Human-readable name of the device",
|
||||
SPA_PROP_FLAG_READABLE,
|
||||
SPA_PROP_TYPE_STRING, 127,
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaXvSinkProps, device_name) },
|
||||
{ PROP_ID_DEVICE_FD, "device-fd", "Device file descriptor",
|
||||
NULL },
|
||||
{ PROP_ID_DEVICE_FD, offsetof (SpaXvSinkProps, device_fd),
|
||||
"device-fd", "Device file descriptor",
|
||||
SPA_PROP_FLAG_READABLE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL,
|
||||
offsetof (SpaXvSinkProps, device_fd) },
|
||||
NULL },
|
||||
};
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -308,12 +308,14 @@ spa_xv_sink_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_video_raw_format_init (&this->raw_format[0]);
|
||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&this->format[0]);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &this->raw_format[0].format;
|
||||
*format = &this->format[0].format;
|
||||
*(int*)state = ++index;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -345,12 +347,12 @@ spa_xv_sink_node_port_set_format (SpaNode *node,
|
|||
|
||||
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
|
||||
if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
||||
if ((res = spa_video_raw_format_parse (format, &this->raw_format[0]) < 0))
|
||||
if ((res = spa_format_video_parse (format, &this->format[0]) < 0))
|
||||
return res;
|
||||
|
||||
f = &this->raw_format[0].format;
|
||||
tf = &this->raw_format[1].format;
|
||||
fs = sizeof (SpaVideoRawFormat);
|
||||
f = &this->format[0].format;
|
||||
tf = &this->format[1].format;
|
||||
fs = sizeof (SpaVideoFormat);
|
||||
} else
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
} else
|
||||
|
|
|
|||
|
|
@ -318,18 +318,18 @@ negotiate_formats (AppData *data)
|
|||
f.fmt.props.n_prop_info = 3;
|
||||
f.fmt.props.prop_info = f.infos;
|
||||
|
||||
spa_video_raw_fill_prop_info (&f.infos[0],
|
||||
spa_prop_info_fill_video (&f.infos[0],
|
||||
SPA_PROP_ID_VIDEO_FORMAT,
|
||||
offsetof (VideoFormat, format));
|
||||
f.format = SPA_VIDEO_FORMAT_YUY2;
|
||||
|
||||
spa_video_raw_fill_prop_info (&f.infos[1],
|
||||
spa_prop_info_fill_video (&f.infos[1],
|
||||
SPA_PROP_ID_VIDEO_SIZE,
|
||||
offsetof (VideoFormat, size));
|
||||
f.size.width = 320;
|
||||
f.size.height = 240;
|
||||
|
||||
spa_video_raw_fill_prop_info (&f.infos[2],
|
||||
spa_prop_info_fill_video (&f.infos[2],
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||
offsetof (VideoFormat, framerate));
|
||||
f.framerate.num = 25;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue