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 {
|
typedef struct {
|
||||||
bool cleanup;
|
bool cleanup;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
int fd;
|
|
||||||
off_t offset;
|
|
||||||
size_t size;
|
|
||||||
bool used;
|
bool used;
|
||||||
SpaBuffer *buf;
|
SpaBuffer *buf;
|
||||||
} BufferId;
|
} BufferId;
|
||||||
|
|
@ -53,10 +50,8 @@ typedef struct {
|
||||||
static void
|
static void
|
||||||
clear_buffer_id (BufferId *id)
|
clear_buffer_id (BufferId *id)
|
||||||
{
|
{
|
||||||
munmap (id->buf, id->size);
|
spa_memory_unref (&id->buf->mem.mem);
|
||||||
id->buf = NULL;
|
id->buf = NULL;
|
||||||
close (id->fd);
|
|
||||||
id->fd = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _PinosStreamPrivate
|
struct _PinosStreamPrivate
|
||||||
|
|
@ -822,45 +817,46 @@ parse_control (PinosStream *stream,
|
||||||
spa_memory_unref (&p.mem);
|
spa_memory_unref (&p.mem);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_CONTROL_CMD_ADD_BUFFER:
|
case SPA_CONTROL_CMD_USE_BUFFERS:
|
||||||
{
|
{
|
||||||
SpaControlCmdAddBuffer p;
|
SpaControlCmdUseBuffers p;
|
||||||
BufferId bid;
|
BufferId bid;
|
||||||
SpaMemory *mem;
|
unsigned int i;
|
||||||
|
SpaControlBuilder builder;
|
||||||
|
SpaControl control;
|
||||||
|
|
||||||
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
g_debug ("add buffer %d, %d", p.buffer_id, p.mem.mem.id);
|
/* clear previous buffers */
|
||||||
mem = spa_memory_find (&p.mem.mem);
|
g_array_set_size (priv->buffer_ids, 0);
|
||||||
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);
|
|
||||||
|
|
||||||
if (bid.id != priv->buffer_ids->len) {
|
for (i = 0; i < p.n_buffers; i++) {
|
||||||
g_warning ("unexpected id %u found, expected %u", bid.id, priv->buffer_ids->len);
|
bid.buf = p.buffers[i];
|
||||||
priv->in_order = FALSE;
|
bid.cleanup = false;
|
||||||
|
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, bid.id);
|
||||||
}
|
}
|
||||||
g_array_append_val (priv->buffer_ids, bid);
|
|
||||||
g_signal_emit (stream, signals[SIGNAL_ADD_BUFFER], 0, p.buffer_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SPA_CONTROL_CMD_REMOVE_BUFFER:
|
|
||||||
{
|
|
||||||
SpaControlCmdRemoveBuffer p;
|
|
||||||
BufferId *bid;
|
|
||||||
|
|
||||||
if (spa_control_iter_parse_cmd (&it, &p) < 0)
|
control_builder_init (stream, &builder);
|
||||||
break;
|
if (p.n_buffers) {
|
||||||
|
add_state_change (stream, &builder, SPA_NODE_STATE_PAUSED);
|
||||||
g_debug ("remove buffer %d", p.buffer_id);
|
} else {
|
||||||
if ((bid = find_buffer (stream, p.buffer_id))) {
|
add_state_change (stream, &builder, SPA_NODE_STATE_READY);
|
||||||
bid->cleanup = TRUE;
|
|
||||||
bid->used = TRUE;
|
|
||||||
g_signal_emit (stream, signals[SIGNAL_REMOVE_BUFFER], 0, p.buffer_id);
|
|
||||||
}
|
}
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
||||||
|
|
@ -875,7 +871,7 @@ parse_control (PinosStream *stream,
|
||||||
|
|
||||||
g_signal_emit (stream, signals[SIGNAL_NEW_BUFFER], 0, p.buffer_id);
|
g_signal_emit (stream, signals[SIGNAL_NEW_BUFFER], 0, p.buffer_id);
|
||||||
|
|
||||||
send_need_input (stream, 0);
|
send_need_input (stream, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_CONTROL_CMD_REUSE_BUFFER:
|
case SPA_CONTROL_CMD_REUSE_BUFFER:
|
||||||
|
|
@ -919,7 +915,6 @@ on_socket_condition (GSocket *socket,
|
||||||
case G_IO_IN:
|
case G_IO_IN:
|
||||||
{
|
{
|
||||||
SpaControl *control = &priv->recv_control;
|
SpaControl *control = &priv->recv_control;
|
||||||
guint i;
|
|
||||||
|
|
||||||
if (spa_control_read (control,
|
if (spa_control_read (control,
|
||||||
priv->fd,
|
priv->fd,
|
||||||
|
|
@ -933,17 +928,6 @@ on_socket_condition (GSocket *socket,
|
||||||
|
|
||||||
parse_control (stream, control);
|
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);
|
spa_control_clear (control);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ calc_size (GstCapsFeatures *cf, GstStructure *cs, guint *n_infos, guint *n_range
|
||||||
n_ranges[0] += c;
|
n_ranges[0] += c;
|
||||||
n_datas[0] += (1 + c) * sizeof (uint32_t);
|
n_datas[0] += (1 + c) * sizeof (uint32_t);
|
||||||
}
|
}
|
||||||
|
} else if (gst_structure_has_name (cs, "image/jpeg")) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,9 +148,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||||
if (val) {
|
if (val) {
|
||||||
SpaVideoFormat *sv = p;
|
SpaVideoFormat *sv = p;
|
||||||
|
|
||||||
spa_video_raw_fill_prop_info (&bpi[pi],
|
spa_prop_info_fill_video (&bpi[pi],
|
||||||
SPA_PROP_ID_VIDEO_FORMAT,
|
SPA_PROP_ID_VIDEO_FORMAT,
|
||||||
SPA_PTRDIFF (p, f));
|
SPA_PTRDIFF (p, f));
|
||||||
|
|
||||||
if (G_VALUE_TYPE (val) == G_TYPE_STRING) {
|
if (G_VALUE_TYPE (val) == G_TYPE_STRING) {
|
||||||
*sv = gst_video_format_from_string (g_value_get_string (val));
|
*sv = gst_video_format_from_string (g_value_get_string (val));
|
||||||
|
|
@ -171,7 +172,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||||
if (val || val2) {
|
if (val || val2) {
|
||||||
SpaRectangle *sv = p;
|
SpaRectangle *sv = p;
|
||||||
|
|
||||||
spa_video_raw_fill_prop_info (&bpi[pi],
|
spa_prop_info_fill_video (&bpi[pi],
|
||||||
SPA_PROP_ID_VIDEO_SIZE,
|
SPA_PROP_ID_VIDEO_SIZE,
|
||||||
SPA_PTRDIFF (p, f));
|
SPA_PTRDIFF (p, f));
|
||||||
|
|
||||||
|
|
@ -224,9 +225,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||||
if (val) {
|
if (val) {
|
||||||
SpaFraction *sv = p;
|
SpaFraction *sv = p;
|
||||||
|
|
||||||
spa_video_raw_fill_prop_info (&bpi[pi],
|
spa_prop_info_fill_video (&bpi[pi],
|
||||||
SPA_PROP_ID_VIDEO_FRAMERATE,
|
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||||
SPA_PTRDIFF (p, f));
|
SPA_PTRDIFF (p, f));
|
||||||
|
|
||||||
if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) {
|
if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) {
|
||||||
sv->num = gst_value_get_fraction_numerator (val);
|
sv->num = gst_value_get_fraction_numerator (val);
|
||||||
|
|
@ -284,9 +285,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||||
if (val) {
|
if (val) {
|
||||||
SpaAudioFormat *sv = p;
|
SpaAudioFormat *sv = p;
|
||||||
|
|
||||||
spa_audio_raw_fill_prop_info (&bpi[pi],
|
spa_prop_info_fill_audio (&bpi[pi],
|
||||||
SPA_PROP_ID_AUDIO_FORMAT,
|
SPA_PROP_ID_AUDIO_FORMAT,
|
||||||
SPA_PTRDIFF (p, f));
|
SPA_PTRDIFF (p, f));
|
||||||
|
|
||||||
if (G_VALUE_TYPE (val) == G_TYPE_STRING) {
|
if (G_VALUE_TYPE (val) == G_TYPE_STRING) {
|
||||||
*sv = gst_audio_format_from_string (g_value_get_string (val));
|
*sv = gst_audio_format_from_string (g_value_get_string (val));
|
||||||
|
|
@ -307,9 +308,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||||
if (val) {
|
if (val) {
|
||||||
SpaAudioLayout *sv = p;
|
SpaAudioLayout *sv = p;
|
||||||
|
|
||||||
spa_audio_raw_fill_prop_info (&bpi[pi],
|
spa_prop_info_fill_audio (&bpi[pi],
|
||||||
SPA_PROP_ID_AUDIO_LAYOUT,
|
SPA_PROP_ID_AUDIO_LAYOUT,
|
||||||
SPA_PTRDIFF (p, f));
|
SPA_PTRDIFF (p, f));
|
||||||
|
|
||||||
if (G_VALUE_TYPE (val) == G_TYPE_STRING) {
|
if (G_VALUE_TYPE (val) == G_TYPE_STRING) {
|
||||||
const gchar *s = g_value_get_string (val);
|
const gchar *s = g_value_get_string (val);
|
||||||
|
|
@ -334,9 +335,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||||
if (val) {
|
if (val) {
|
||||||
uint32_t *sv = p;
|
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_PROP_ID_AUDIO_RATE,
|
||||||
SPA_PTRDIFF (p, f));
|
SPA_PTRDIFF (p, f));
|
||||||
|
|
||||||
if (G_VALUE_TYPE (val) == G_TYPE_INT) {
|
if (G_VALUE_TYPE (val) == G_TYPE_INT) {
|
||||||
*sv = g_value_get_int (val);
|
*sv = g_value_get_int (val);
|
||||||
|
|
@ -357,9 +358,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||||
if (val) {
|
if (val) {
|
||||||
uint32_t *sv = p;
|
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_PROP_ID_AUDIO_CHANNELS,
|
||||||
SPA_PTRDIFF (p, f));
|
SPA_PTRDIFF (p, f));
|
||||||
|
|
||||||
if (G_VALUE_TYPE (val) == G_TYPE_INT) {
|
if (G_VALUE_TYPE (val) == G_TYPE_INT) {
|
||||||
*sv = g_value_get_int (val);
|
*sv = g_value_get_int (val);
|
||||||
|
|
@ -376,6 +377,9 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||||
}
|
}
|
||||||
pi++;
|
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;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
@ -431,16 +435,21 @@ gst_caps_from_format (SpaFormat *format)
|
||||||
GstCaps *res = NULL;
|
GstCaps *res = NULL;
|
||||||
|
|
||||||
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
|
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
|
||||||
|
SpaFormatVideo f;
|
||||||
|
|
||||||
|
spa_format_video_parse (format, &f);
|
||||||
|
|
||||||
if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
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",
|
res = gst_caps_new_simple ("video/x-raw",
|
||||||
"format", G_TYPE_STRING, gst_video_format_to_string (f.info.format),
|
"format", G_TYPE_STRING, gst_video_format_to_string (f.info.raw.format),
|
||||||
"width", G_TYPE_INT, f.info.size.width,
|
"width", G_TYPE_INT, f.info.raw.size.width,
|
||||||
"height", G_TYPE_INT, f.info.size.height,
|
"height", G_TYPE_INT, f.info.raw.size.height,
|
||||||
"framerate", GST_TYPE_FRACTION, f.info.framerate.num, f.info.framerate.denom,
|
"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);
|
NULL);
|
||||||
}
|
}
|
||||||
} else if (format->media_type == SPA_MEDIA_TYPE_AUDIO) {
|
} else if (format->media_type == SPA_MEDIA_TYPE_AUDIO) {
|
||||||
|
|
|
||||||
|
|
@ -224,25 +224,32 @@ setup_node (PinosSpaV4l2Source *this)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stop_pipeline (PinosSpaV4l2Source *this)
|
pause_pipeline (PinosSpaV4l2Source *this)
|
||||||
{
|
{
|
||||||
PinosSpaV4l2SourcePrivate *priv = this->priv;
|
|
||||||
PinosNode *node = PINOS_NODE (this);
|
PinosNode *node = PINOS_NODE (this);
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
SpaCommand cmd;
|
SpaCommand cmd;
|
||||||
|
|
||||||
g_debug ("spa-v4l2-source %p: stopping pipeline", this);
|
g_debug ("spa-v4l2-source %p: pause pipeline", this);
|
||||||
|
|
||||||
if (priv->running) {
|
|
||||||
priv->running = false;
|
|
||||||
pthread_join (priv->thread, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.type = SPA_COMMAND_PAUSE;
|
cmd.type = SPA_COMMAND_PAUSE;
|
||||||
if ((res = spa_node_send_command (node->node, &cmd)) < 0)
|
if ((res = spa_node_send_command (node->node, &cmd)) < 0)
|
||||||
g_debug ("got error %d", res);
|
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
|
static void
|
||||||
destroy_pipeline (PinosSpaV4l2Source *this)
|
destroy_pipeline (PinosSpaV4l2Source *this)
|
||||||
{
|
{
|
||||||
|
|
@ -259,13 +266,14 @@ set_state (PinosNode *node,
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case PINOS_NODE_STATE_SUSPENDED:
|
case PINOS_NODE_STATE_SUSPENDED:
|
||||||
|
suspend_pipeline (this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PINOS_NODE_STATE_INITIALIZING:
|
case PINOS_NODE_STATE_INITIALIZING:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PINOS_NODE_STATE_IDLE:
|
case PINOS_NODE_STATE_IDLE:
|
||||||
stop_pipeline (this);
|
pause_pipeline (this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PINOS_NODE_STATE_RUNNING:
|
case PINOS_NODE_STATE_RUNNING:
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ struct _PinosLinkPrivate
|
||||||
gboolean active;
|
gboolean active;
|
||||||
gboolean negotiated;
|
gboolean negotiated;
|
||||||
gboolean allocated;
|
gboolean allocated;
|
||||||
|
gboolean started;
|
||||||
|
|
||||||
PinosPort *output;
|
PinosPort *output;
|
||||||
PinosPort *input;
|
PinosPort *input;
|
||||||
|
|
@ -227,14 +228,16 @@ do_negotiate (PinosLink *this)
|
||||||
|
|
||||||
g_debug ("link %p: doing set format", this);
|
g_debug ("link %p: doing set format", this);
|
||||||
|
|
||||||
|
priv->negotiated = TRUE;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
if ((res = spa_node_port_enum_formats (priv->input_node,
|
if ((res = spa_node_port_enum_formats (priv->input_node,
|
||||||
priv->input_port,
|
priv->input_port,
|
||||||
&filter,
|
&filter,
|
||||||
NULL,
|
NULL,
|
||||||
&istate)) < 0) {
|
&istate)) < 0) {
|
||||||
g_warning ("error enum formats: %d", res);
|
g_warning ("error input enum formats: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
spa_debug_format (filter);
|
spa_debug_format (filter);
|
||||||
|
|
||||||
|
|
@ -247,26 +250,30 @@ again:
|
||||||
ostate = NULL;
|
ostate = NULL;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
g_warning ("error enum formats: %d", res);
|
g_warning ("error output enum formats: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
spa_debug_format (format);
|
|
||||||
|
|
||||||
spa_format_fixate (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) {
|
if ((res = spa_node_port_set_format (priv->output_node, priv->output_port, 0, format)) < 0) {
|
||||||
g_warning ("error set format output: %d", res);
|
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) {
|
if ((res = spa_node_port_set_format (priv->input_node, priv->input_port, 0, format)) < 0) {
|
||||||
g_warning ("error set format input: %d", res);
|
g_warning ("error set format input: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->negotiated = TRUE;
|
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
{
|
||||||
|
priv->negotiated = FALSE;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
@ -281,13 +288,15 @@ do_allocation (PinosLink *this)
|
||||||
/* find out what's possible */
|
/* find out what's possible */
|
||||||
if ((res = spa_node_port_get_info (priv->output_node, priv->output_port, &oinfo)) < 0) {
|
if ((res = spa_node_port_get_info (priv->output_node, priv->output_port, &oinfo)) < 0) {
|
||||||
g_warning ("error get port info: %d", res);
|
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) {
|
if ((res = spa_node_port_get_info (priv->input_node, priv->input_port, &iinfo)) < 0) {
|
||||||
g_warning ("error get port info: %d", res);
|
g_warning ("error get port info: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->allocated = TRUE;
|
||||||
|
|
||||||
spa_debug_port_info (oinfo);
|
spa_debug_port_info (oinfo);
|
||||||
spa_debug_port_info (iinfo);
|
spa_debug_port_info (iinfo);
|
||||||
|
|
||||||
|
|
@ -311,7 +320,7 @@ do_allocation (PinosLink *this)
|
||||||
priv->in_buffers,
|
priv->in_buffers,
|
||||||
&priv->n_in_buffers)) < 0) {
|
&priv->n_in_buffers)) < 0) {
|
||||||
g_warning ("error alloc buffers: %d", res);
|
g_warning ("error alloc buffers: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
memcpy (priv->out_buffers, priv->in_buffers, priv->n_in_buffers * sizeof (SpaBuffer*));
|
memcpy (priv->out_buffers, priv->in_buffers, priv->n_in_buffers * sizeof (SpaBuffer*));
|
||||||
priv->n_out_buffers = priv->n_in_buffers;
|
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;
|
in_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
|
||||||
} else {
|
} else {
|
||||||
g_warning ("error no common allocation found");
|
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) {
|
if (in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) {
|
||||||
|
|
@ -329,7 +339,7 @@ do_allocation (PinosLink *this)
|
||||||
oinfo->params, oinfo->n_params,
|
oinfo->params, oinfo->n_params,
|
||||||
priv->in_buffers, &priv->n_in_buffers)) < 0) {
|
priv->in_buffers, &priv->n_in_buffers)) < 0) {
|
||||||
g_warning ("error alloc buffers: %d", res);
|
g_warning ("error alloc buffers: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
priv->input->n_buffers = priv->n_in_buffers;
|
priv->input->n_buffers = priv->n_in_buffers;
|
||||||
priv->input->buffers = priv->in_buffers;
|
priv->input->buffers = priv->in_buffers;
|
||||||
|
|
@ -339,7 +349,7 @@ do_allocation (PinosLink *this)
|
||||||
iinfo->params, iinfo->n_params,
|
iinfo->params, iinfo->n_params,
|
||||||
priv->out_buffers, &priv->n_out_buffers)) < 0) {
|
priv->out_buffers, &priv->n_out_buffers)) < 0) {
|
||||||
g_warning ("error alloc buffers: %d", res);
|
g_warning ("error alloc buffers: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
priv->output->n_buffers = priv->n_out_buffers;
|
priv->output->n_buffers = priv->n_out_buffers;
|
||||||
priv->output->buffers = priv->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,
|
if ((res = spa_node_port_use_buffers (priv->input_node, priv->input_port,
|
||||||
priv->out_buffers, priv->n_out_buffers)) < 0) {
|
priv->out_buffers, priv->n_out_buffers)) < 0) {
|
||||||
g_warning ("error use buffers: %d", res);
|
g_warning ("error use buffers: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
priv->input->n_buffers = priv->n_out_buffers;
|
priv->input->n_buffers = priv->n_out_buffers;
|
||||||
priv->input->buffers = priv->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,
|
if ((res = spa_node_port_use_buffers (priv->output_node, priv->output_port,
|
||||||
priv->in_buffers, priv->n_in_buffers)) < 0) {
|
priv->in_buffers, priv->n_in_buffers)) < 0) {
|
||||||
g_warning ("error use buffers: %d", res);
|
g_warning ("error use buffers: %d", res);
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
priv->output->n_buffers = priv->n_in_buffers;
|
priv->output->n_buffers = priv->n_in_buffers;
|
||||||
priv->output->buffers = priv->in_buffers;
|
priv->output->buffers = priv->in_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->allocated = TRUE;
|
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
{
|
||||||
|
priv->allocated = FALSE;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
@ -375,6 +389,8 @@ do_start (PinosLink *this)
|
||||||
SpaCommand cmd;
|
SpaCommand cmd;
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
|
|
||||||
|
priv->started = TRUE;
|
||||||
|
|
||||||
cmd.type = SPA_COMMAND_START;
|
cmd.type = SPA_COMMAND_START;
|
||||||
if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0)
|
if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0)
|
||||||
g_warning ("got error %d", res);
|
g_warning ("got error %d", res);
|
||||||
|
|
@ -391,6 +407,8 @@ do_pause (PinosLink *this)
|
||||||
SpaCommand cmd;
|
SpaCommand cmd;
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
|
|
||||||
|
priv->started = FALSE;
|
||||||
|
|
||||||
cmd.type = SPA_COMMAND_PAUSE;
|
cmd.type = SPA_COMMAND_PAUSE;
|
||||||
if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0)
|
if ((res = spa_node_send_command (priv->input_node, &cmd)) < 0)
|
||||||
g_warning ("got error %d", res);
|
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);
|
g_debug ("link %p: input %d, output %d", this, priv->input_state, priv->output_state);
|
||||||
|
|
||||||
if (priv->input_state == SPA_NODE_STATE_CONFIGURE &&
|
if (priv->input_state >= SPA_NODE_STATE_CONFIGURE &&
|
||||||
priv->output_state == SPA_NODE_STATE_CONFIGURE &&
|
priv->output_state >= SPA_NODE_STATE_CONFIGURE &&
|
||||||
!priv->negotiated) {
|
!priv->negotiated) {
|
||||||
if ((res = do_negotiate (this)) < 0)
|
if ((res = do_negotiate (this)) < 0)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (priv->input_state == SPA_NODE_STATE_READY &&
|
if (priv->input_state >= SPA_NODE_STATE_READY &&
|
||||||
priv->output_state == SPA_NODE_STATE_READY &&
|
priv->output_state >= SPA_NODE_STATE_READY &&
|
||||||
!priv->allocated) {
|
!priv->allocated) {
|
||||||
if ((res = do_allocation (this)) < 0)
|
if ((res = do_allocation (this)) < 0)
|
||||||
return res;
|
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)
|
if ((res = do_start (this)) < 0)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -546,10 +567,15 @@ pinos_link_constructed (GObject * object)
|
||||||
static void
|
static void
|
||||||
pinos_link_dispose (GObject * object)
|
pinos_link_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
PinosLink *link = PINOS_LINK (object);
|
PinosLink *this = PINOS_LINK (object);
|
||||||
PinosLinkPrivate *priv = link->priv;
|
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->input, priv->input_id);
|
||||||
pinos_port_remove_send_cb (priv->output, priv->output_id);
|
pinos_port_remove_send_cb (priv->output, priv->output_id);
|
||||||
|
|
@ -560,7 +586,7 @@ pinos_link_dispose (GObject * object)
|
||||||
}
|
}
|
||||||
priv->input = NULL;
|
priv->input = NULL;
|
||||||
priv->output = NULL;
|
priv->output = NULL;
|
||||||
link_unregister_object (link);
|
link_unregister_object (this);
|
||||||
|
|
||||||
G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object);
|
G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,10 @@ typedef enum {
|
||||||
SPA_PROP_ID_AUDIO_RAW_INFO,
|
SPA_PROP_ID_AUDIO_RAW_INFO,
|
||||||
} SpaPropIdAudio;
|
} SpaPropIdAudio;
|
||||||
|
|
||||||
|
SpaResult spa_prop_info_fill_audio (SpaPropInfo *info,
|
||||||
|
SpaPropIdAudio id,
|
||||||
|
size_t offset);
|
||||||
|
|
||||||
struct _SpaAudioRawFormat {
|
struct _SpaAudioRawFormat {
|
||||||
SpaFormat format;
|
SpaFormat format;
|
||||||
SpaAudioRawInfo info;
|
SpaAudioRawInfo info;
|
||||||
|
|
@ -48,10 +52,6 @@ SpaResult spa_audio_raw_format_init (SpaAudioRawFormat *format);
|
||||||
SpaResult spa_audio_raw_format_parse (const SpaFormat *format,
|
SpaResult spa_audio_raw_format_parse (const SpaFormat *format,
|
||||||
SpaAudioRawFormat *rawformat);
|
SpaAudioRawFormat *rawformat);
|
||||||
|
|
||||||
SpaResult spa_audio_raw_fill_prop_info (SpaPropInfo *info,
|
|
||||||
SpaPropIdAudio id,
|
|
||||||
size_t offset);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -81,10 +81,9 @@ typedef enum {
|
||||||
SPA_CONTROL_CMD_ADD_MEM = 64,
|
SPA_CONTROL_CMD_ADD_MEM = 64,
|
||||||
SPA_CONTROL_CMD_REMOVE_MEM = 65,
|
SPA_CONTROL_CMD_REMOVE_MEM = 65,
|
||||||
|
|
||||||
SPA_CONTROL_CMD_ADD_BUFFER = 66,
|
SPA_CONTROL_CMD_USE_BUFFERS = 66,
|
||||||
SPA_CONTROL_CMD_REMOVE_BUFFER = 67,
|
SPA_CONTROL_CMD_PROCESS_BUFFER = 67,
|
||||||
SPA_CONTROL_CMD_PROCESS_BUFFER = 68,
|
SPA_CONTROL_CMD_REUSE_BUFFER = 68,
|
||||||
SPA_CONTROL_CMD_REUSE_BUFFER = 69,
|
|
||||||
|
|
||||||
} SpaControlCmd;
|
} SpaControlCmd;
|
||||||
|
|
||||||
|
|
@ -184,18 +183,12 @@ typedef struct {
|
||||||
SpaMemoryRef mem;
|
SpaMemoryRef mem;
|
||||||
} SpaControlCmdRemoveMem;
|
} SpaControlCmdRemoveMem;
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_ADD_BUFFER */
|
/* SPA_CONTROL_CMD_USE_BUFFERS */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t port_id;
|
uint32_t port_id;
|
||||||
uint32_t buffer_id;
|
unsigned int n_buffers;
|
||||||
SpaMemoryChunk mem;
|
SpaBuffer **buffers;
|
||||||
} SpaControlCmdAddBuffer;
|
} SpaControlCmdUseBuffers;
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_REMOVE_BUFFER */
|
|
||||||
typedef struct {
|
|
||||||
uint32_t port_id;
|
|
||||||
uint32_t buffer_id;
|
|
||||||
} SpaControlCmdRemoveBuffer;
|
|
||||||
|
|
||||||
/* SPA_CONTROL_CMD_PROCESS_BUFFER */
|
/* SPA_CONTROL_CMD_PROCESS_BUFFER */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ typedef struct {
|
||||||
/**
|
/**
|
||||||
* SpaPropInfo:
|
* SpaPropInfo:
|
||||||
* @id: unique id
|
* @id: unique id
|
||||||
|
* @offset: offset in structure with data
|
||||||
* @name: human readable name
|
* @name: human readable name
|
||||||
* @description: description of the property
|
* @description: description of the property
|
||||||
* @flags: property flags
|
* @flags: property flags
|
||||||
|
|
@ -123,10 +124,10 @@ typedef struct {
|
||||||
* @n_range_values: number of elements in @range_values
|
* @n_range_values: number of elements in @range_values
|
||||||
* @range_values: array of possible values
|
* @range_values: array of possible values
|
||||||
* @tags: extra tags, NULL terminated
|
* @tags: extra tags, NULL terminated
|
||||||
* @offset: offset in structure with data
|
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
size_t offset;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *description;
|
const char *description;
|
||||||
SpaPropFlags flags;
|
SpaPropFlags flags;
|
||||||
|
|
@ -136,7 +137,6 @@ typedef struct {
|
||||||
unsigned int n_range_values;
|
unsigned int n_range_values;
|
||||||
const SpaPropRangeInfo *range_values;
|
const SpaPropRangeInfo *range_values;
|
||||||
const char **tags;
|
const char **tags;
|
||||||
size_t offset;
|
|
||||||
} SpaPropInfo;
|
} SpaPropInfo;
|
||||||
|
|
||||||
typedef struct {
|
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/format.h>
|
||||||
#include <spa/video/raw.h>
|
#include <spa/video/raw.h>
|
||||||
|
#include <spa/video/encoded.h>
|
||||||
|
|
||||||
typedef struct _SpaVideoRawFormat SpaVideoRawFormat;
|
typedef struct _SpaFormatVideo SpaFormatVideo;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SPA_PROP_ID_VIDEO_FORMAT = SPA_PROP_ID_MEDIA_CUSTOM_START,
|
SPA_PROP_ID_VIDEO_FORMAT = SPA_PROP_ID_MEDIA_CUSTOM_START,
|
||||||
|
|
@ -47,20 +48,24 @@ typedef enum {
|
||||||
SPA_PROP_ID_VIDEO_RAW_INFO,
|
SPA_PROP_ID_VIDEO_RAW_INFO,
|
||||||
} SpaPropIdVideo;
|
} SpaPropIdVideo;
|
||||||
|
|
||||||
struct _SpaVideoRawFormat {
|
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;
|
SpaFormat format;
|
||||||
SpaVideoRawInfo info;
|
union {
|
||||||
|
SpaVideoInfoRaw raw;
|
||||||
|
SpaVideoInfoJPEG jpeg;
|
||||||
|
} 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,
|
|
||||||
SpaPropIdVideo id,
|
|
||||||
size_t offset);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct _SpaVideoRawInfo SpaVideoRawInfo;
|
typedef struct _SpaVideoInfoRaw SpaVideoInfoRaw;
|
||||||
|
|
||||||
#include <spa/props.h>
|
#include <spa/props.h>
|
||||||
#include <spa/video/chroma.h>
|
#include <spa/video/chroma.h>
|
||||||
|
|
@ -146,7 +146,7 @@ typedef enum {
|
||||||
} SpaVideoInterlaceMode;
|
} SpaVideoInterlaceMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SpaVideoRawInfo:
|
* SpaVideoInfoRaw:
|
||||||
* @format: the format
|
* @format: the format
|
||||||
* @size: the frame size of the video
|
* @size: the frame size of the video
|
||||||
* @framerate: the framerate of the video 0/1 means variable rate
|
* @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
|
* @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
|
* @color_primaries: color primaries. used to convert between R'G'B' and CIE XYZ
|
||||||
*/
|
*/
|
||||||
struct _SpaVideoRawInfo {
|
struct _SpaVideoInfoRaw {
|
||||||
SpaVideoFormat format;
|
SpaVideoFormat format;
|
||||||
SpaRectangle size;
|
SpaRectangle size;
|
||||||
SpaFraction framerate;
|
SpaFraction framerate;
|
||||||
|
|
|
||||||
|
|
@ -135,55 +135,95 @@ static const SpaPropRangeInfo uint32_range[] = {
|
||||||
{ "max", "Maximum value", 4, &max_uint32 },
|
{ "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_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_format_range), format_format_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_format_range), format_format_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioRawFormat, info.format) },
|
{ SPA_PROP_ID_AUDIO_FLAGS, 0,
|
||||||
{ SPA_PROP_ID_AUDIO_FLAGS, "flags", "Sample Flags",
|
"flags", "Sample Flags",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (flags_range), flags_range,
|
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (flags_range), flags_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioRawFormat, info.flags) },
|
{ SPA_PROP_ID_AUDIO_LAYOUT, 0,
|
||||||
{ SPA_PROP_ID_AUDIO_LAYOUT, "layout", "Sample Layout",
|
"layout", "Sample Layout",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (layouts_range), layouts_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (layouts_range), layouts_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioRawFormat, info.layout) },
|
{ SPA_PROP_ID_AUDIO_RATE, 0,
|
||||||
{ SPA_PROP_ID_AUDIO_RATE, "rate", "Audio sample rate",
|
"rate", "Audio sample rate",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioRawFormat, info.rate) },
|
{ SPA_PROP_ID_AUDIO_CHANNELS, 0,
|
||||||
{ SPA_PROP_ID_AUDIO_CHANNELS, "channels", "Audio channels",
|
"channels", "Audio channels",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioRawFormat, info.channels) },
|
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, 0,
|
||||||
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, "channel-mask", "Audio channel mask",
|
"channel-mask", "Audio channel mask",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_BITMASK, sizeof (uint32_t),
|
SPA_PROP_TYPE_BITMASK, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioRawFormat, info.channel_mask) },
|
{ SPA_PROP_ID_AUDIO_RAW_INFO, 0,
|
||||||
{ SPA_PROP_ID_AUDIO_RAW_INFO, "info", "the SpaAudioRawInfo structure",
|
"info", "the SpaAudioRawInfo structure",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_POINTER, sizeof (SpaAudioRawInfo),
|
SPA_PROP_TYPE_POINTER, sizeof (SpaAudioRawInfo),
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioRawFormat, info) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
SpaResult
|
||||||
spa_audio_raw_format_init (SpaAudioRawFormat *format)
|
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_type = SPA_MEDIA_TYPE_AUDIO;
|
||||||
format->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW;
|
format->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW;
|
||||||
format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
|
format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
|
||||||
|
|
@ -227,23 +267,3 @@ fallback:
|
||||||
|
|
||||||
return res;
|
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));
|
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
|
SpaResult
|
||||||
spa_control_iter_parse_cmd (SpaControlIter *iter,
|
spa_control_iter_parse_cmd (SpaControlIter *iter,
|
||||||
void *command)
|
void *command)
|
||||||
|
|
@ -542,16 +563,8 @@ spa_control_iter_parse_cmd (SpaControlIter *iter,
|
||||||
memcpy (command, si->data, sizeof (SpaControlCmdRemoveMem));
|
memcpy (command, si->data, sizeof (SpaControlCmdRemoveMem));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPA_CONTROL_CMD_ADD_BUFFER:
|
case SPA_CONTROL_CMD_USE_BUFFERS:
|
||||||
if (si->size < sizeof (SpaControlCmdAddBuffer))
|
iter_parse_use_buffers (si, command);
|
||||||
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));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
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));
|
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:
|
* spa_control_builder_add_cmd:
|
||||||
* @builder: a #SpaControlBuilder
|
* @builder: a #SpaControlBuilder
|
||||||
|
|
@ -1168,14 +1216,8 @@ spa_control_builder_add_cmd (SpaControlBuilder *builder,
|
||||||
memcpy (p, command, sizeof (SpaControlCmdRemoveMem));
|
memcpy (p, command, sizeof (SpaControlCmdRemoveMem));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPA_CONTROL_CMD_ADD_BUFFER:
|
case SPA_CONTROL_CMD_USE_BUFFERS:
|
||||||
p = builder_add_cmd (sb, cmd, sizeof (SpaControlCmdAddBuffer));
|
builder_add_use_buffers (sb, command);
|
||||||
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));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
||||||
|
|
|
||||||
|
|
@ -169,18 +169,31 @@ spa_debug_dump_mem (const void *mem, size_t size)
|
||||||
struct media_type_name {
|
struct media_type_name {
|
||||||
const char *name;
|
const char *name;
|
||||||
} media_type_names[] = {
|
} media_type_names[] = {
|
||||||
{ "unknown" },
|
{ "invalid" },
|
||||||
{ "audio" },
|
{ "audio" },
|
||||||
{ "video" },
|
{ "video" },
|
||||||
|
{ "image" },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct media_subtype_name {
|
struct media_subtype_name {
|
||||||
const char *name;
|
const char *name;
|
||||||
} media_subtype_names[] = {
|
} media_subtype_names[] = {
|
||||||
{ "unknown" },
|
{ "invalid" },
|
||||||
{ "raw" },
|
{ "raw" },
|
||||||
{ "h264" },
|
{ "h264" },
|
||||||
{ "mjpg" },
|
{ "mjpg" },
|
||||||
|
{ "dv" },
|
||||||
|
{ "mpegts" },
|
||||||
|
{ "h263" },
|
||||||
|
{ "mpeg1" },
|
||||||
|
{ "mpeg2" },
|
||||||
|
{ "mpeg4" },
|
||||||
|
{ "xvid" },
|
||||||
|
{ "vc1" },
|
||||||
|
{ "vp8" },
|
||||||
|
{ "vp9" },
|
||||||
|
{ "jpeg" },
|
||||||
|
{ "bayer" },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct prop_type_name {
|
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);
|
res = spa_props_get_prop (props, i, &value);
|
||||||
|
|
||||||
fprintf (stderr, ". Current: ");
|
fprintf (stderr, "Current: ");
|
||||||
if (res == SPA_RESULT_OK)
|
if (res == SPA_RESULT_OK)
|
||||||
print_value (info, value.size, value.value);
|
print_value (info, value.size, value.value);
|
||||||
else if (res == SPA_RESULT_PROPERTY_UNSET)
|
else if (res == SPA_RESULT_PROPERTY_UNSET)
|
||||||
|
|
@ -386,14 +399,25 @@ spa_debug_format (const SpaFormat *format)
|
||||||
{
|
{
|
||||||
const SpaProps *props;
|
const SpaProps *props;
|
||||||
int i;
|
int i;
|
||||||
|
const char *media_type;
|
||||||
|
const char *media_subtype;
|
||||||
|
|
||||||
if (format == NULL)
|
if (format == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
props = &format->props;
|
props = &format->props;
|
||||||
|
|
||||||
fprintf (stderr, "%-6s %s/%s\n", "", media_type_names[format->media_type].name,
|
if (format->media_type > 0 && format->media_type < SPA_N_ELEMENTS (media_type_names))
|
||||||
media_subtype_names[format->media_subtype].name);
|
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++) {
|
for (i = 0; i < props->n_prop_info; i++) {
|
||||||
const SpaPropInfo *info = &props->prop_info[i];
|
const SpaPropInfo *info = &props->prop_info[i];
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
#include <spa/video/raw.h>
|
#include <spa/video/raw.h>
|
||||||
#include <spa/video/format.h>
|
#include <spa/video/format.h>
|
||||||
|
|
||||||
static const SpaVideoRawInfo default_info = {
|
static const SpaVideoInfoRaw default_raw_info = {
|
||||||
SPA_VIDEO_FORMAT_UNKNOWN,
|
SPA_VIDEO_FORMAT_UNKNOWN,
|
||||||
{ 320, 240 },
|
{ 320, 240 },
|
||||||
{ 0, 1 },
|
{ 0, 1 },
|
||||||
|
|
@ -371,175 +371,193 @@ static const SpaPropRangeInfo framerate_range[] = {
|
||||||
{ "max", "Maximum value", sizeof (SpaFraction), &max_framerate },
|
{ "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_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_range), format_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_range), format_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.format) },
|
{ SPA_PROP_ID_VIDEO_SIZE, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_SIZE, "size", "Video size",
|
"size", "Video size",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_RECTANGLE, sizeof (SpaRectangle),
|
SPA_PROP_TYPE_RECTANGLE, sizeof (SpaRectangle),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, size_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, size_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.size) },
|
{ SPA_PROP_ID_VIDEO_FRAMERATE, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, "framerate", "Video framerate",
|
"framerate", "Video framerate",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.framerate) },
|
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, "max-framerate", "Video max framerate",
|
"max-framerate", "Video max framerate",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.max_framerate) },
|
{ SPA_PROP_ID_VIDEO_VIEWS, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_VIEWS, "views", "Video number of views",
|
"views", "Video number of views",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.views) },
|
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, "interlace-mode", "Interlace mode",
|
"interlace-mode", "Interlace mode",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (interlace_mode_range), interlace_mode_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (interlace_mode_range), interlace_mode_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.interlace_mode) },
|
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, "pixel-aspect-ratio", "Video pixel aspect ratio",
|
"pixel-aspect-ratio", "Video pixel aspect ratio",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.pixel_aspect_ratio) },
|
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, "multiview-mode", "Multiview mode",
|
"multiview-mode", "Multiview mode",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (multiview_mode_range), multiview_mode_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (multiview_mode_range), multiview_mode_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.multiview_mode) },
|
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, "multiview-flags", "Multiview flags",
|
"multiview-flags", "Multiview flags",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (multiview_flags_range), multiview_flags_range,
|
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (multiview_flags_range), multiview_flags_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.multiview_flags) },
|
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, "chroma-site", "Chroma site",
|
"chroma-site", "Chroma site",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (chroma_site_range), chroma_site_range,
|
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (chroma_site_range), chroma_site_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.chroma_site) },
|
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, "color-range", "Color range",
|
"color-range", "Color range",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_range_range), color_range_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_range_range), color_range_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.color_range) },
|
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, "color-matrix", "Color matrix",
|
"color-matrix", "Color matrix",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_matrix_range), color_matrix_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_matrix_range), color_matrix_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.color_matrix) },
|
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, "transfer-function", "Transfer function",
|
"transfer-function", "Transfer function",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (transfer_function_range), transfer_function_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (transfer_function_range), transfer_function_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.transfer_function) },
|
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, "color-primaries", "Color primaries",
|
"color-primaries", "Color primaries",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_primaries_range), color_primaries_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_primaries_range), color_primaries_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info.color_primaries) },
|
{ SPA_PROP_ID_VIDEO_RAW_INFO, 0,
|
||||||
{ SPA_PROP_ID_VIDEO_RAW_INFO, "info", "the SpaVideoRawInfo structure",
|
"info", "the SpaVideoRawInfo structure",
|
||||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
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,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVideoRawFormat, info) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SpaResult
|
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;
|
int i;
|
||||||
format->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW;
|
|
||||||
format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
|
if (info == NULL)
|
||||||
format->format.props.prop_info = raw_format_prop_info;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
format->format.props.unset_mask = (1 << 14)-1;
|
|
||||||
format->info = default_info;
|
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;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaResult
|
SpaResult
|
||||||
spa_video_raw_format_parse (const SpaFormat *format,
|
spa_format_video_init (SpaMediaType type,
|
||||||
SpaVideoRawFormat *rawformat)
|
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;
|
SpaPropValue value;
|
||||||
const SpaProps *props;
|
const SpaProps *props;
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
|
|
||||||
if ((void *)format == (void *)rawformat)
|
if ((void *)format == (void *)vformat)
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
||||||
if (format->media_type != SPA_MEDIA_TYPE_VIDEO ||
|
if (format->media_type != SPA_MEDIA_TYPE_VIDEO)
|
||||||
format->media_subtype != SPA_MEDIA_SUBTYPE_RAW)
|
|
||||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
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;
|
props = &format->props;
|
||||||
if ((res = spa_props_get_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_RAW_INFO), &value)) < 0)
|
if ((res = spa_props_get_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_RAW_INFO), &value)) < 0)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
if (value.type != SPA_PROP_TYPE_POINTER || value.size != sizeof (SpaVideoRawInfo))
|
if (value.type != SPA_PROP_TYPE_POINTER)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
memcpy (&rawformat->info, value.value, sizeof (SpaVideoRawInfo));
|
memcpy (&vformat->info, value.value, value.size);
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
||||||
fallback:
|
fallback:
|
||||||
res = spa_props_copy (props, &rawformat->format.props);
|
res = spa_props_copy (props, &vformat->format.props);
|
||||||
|
|
||||||
return res;
|
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[] =
|
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_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_STRING, 63,
|
SPA_PROP_TYPE_STRING, 63,
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaALSASinkProps, device) },
|
{ PROP_ID_DEVICE_NAME, offsetof (SpaALSASinkProps, device_name),
|
||||||
{ PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the sound device",
|
"device-name", "Human-readable name of the sound device",
|
||||||
SPA_PROP_FLAG_READABLE,
|
SPA_PROP_FLAG_READABLE,
|
||||||
SPA_PROP_TYPE_STRING, 127,
|
SPA_PROP_TYPE_STRING, 127,
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaALSASinkProps, device_name) },
|
{ PROP_ID_CARD_NAME, offsetof (SpaALSASinkProps, card_name),
|
||||||
{ PROP_ID_CARD_NAME, "card-name", "Human-readable name of the sound card",
|
"card-name", "Human-readable name of the sound card",
|
||||||
SPA_PROP_FLAG_READABLE,
|
SPA_PROP_FLAG_READABLE,
|
||||||
SPA_PROP_TYPE_STRING, 127,
|
SPA_PROP_TYPE_STRING, 127,
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaALSASinkProps, card_name) },
|
{ PROP_ID_BUFFER_TIME, offsetof (SpaALSASinkProps, buffer_time),
|
||||||
{ PROP_ID_BUFFER_TIME, "buffer-time", "The total size of the buffer in time",
|
"buffer-time", "The total size of the buffer in time",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaALSASinkProps, buffer_time) },
|
{ PROP_ID_PERIOD_TIME, offsetof (SpaALSASinkProps, period_time),
|
||||||
{ PROP_ID_PERIOD_TIME, "period-time", "The size of a period in time",
|
"period-time", "The size of a period in time",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaALSASinkProps, period_time) },
|
{ PROP_ID_PERIOD_EVENT, offsetof (SpaALSASinkProps, period_event),
|
||||||
{ PROP_ID_PERIOD_EVENT, "period-event", "Generate an event each period",
|
"period-event", "Generate an event each period",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_BOOL, sizeof (bool),
|
SPA_PROP_TYPE_BOOL, sizeof (bool),
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaALSASinkProps, period_event) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
|
||||||
|
|
@ -84,24 +84,24 @@ enum {
|
||||||
|
|
||||||
static const SpaPropInfo prop_info[] =
|
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_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (wave_range), wave_range,
|
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (wave_range), wave_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioTestSrcProps, wave) },
|
{ PROP_ID_FREQ, offsetof (SpaAudioTestSrcProps, freq),
|
||||||
{ PROP_ID_FREQ, "freq", "Frequency of test signal. The sample rate needs to be at least 4 times higher",
|
"freq", "Frequency of test signal. The sample rate needs to be at least 4 times higher",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, freq_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, freq_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioTestSrcProps, freq) },
|
{ PROP_ID_VOLUME, offsetof (SpaAudioTestSrcProps, volume),
|
||||||
{ PROP_ID_VOLUME, "volume", "The Volume factor",
|
"volume", "The Volume factor",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaAudioTestSrcProps, volume) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -465,7 +465,7 @@ spa_audiotestsrc_node_port_pull_output (SpaNode *node,
|
||||||
{
|
{
|
||||||
SpaAudioTestSrc *this;
|
SpaAudioTestSrc *this;
|
||||||
size_t j, size;
|
size_t j, size;
|
||||||
uint8_t *ptr;
|
uint8_t *ptr = NULL;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool have_error = false;
|
bool have_error = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ struct _FFMpegBuffer {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SpaVideoRawFormat raw_format[2];
|
SpaFormatVideo format[2];
|
||||||
SpaFormat *current_format;
|
SpaFormat *current_format;
|
||||||
bool have_buffers;
|
bool have_buffers;
|
||||||
FFMpegBuffer buffers[MAX_BUFFERS];
|
FFMpegBuffer buffers[MAX_BUFFERS];
|
||||||
|
|
@ -278,12 +278,14 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node,
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return SPA_RESULT_ENUM_END;
|
return SPA_RESULT_ENUM_END;
|
||||||
}
|
}
|
||||||
*format = &s->raw_format[0].format;
|
*format = &s->format[0].format;
|
||||||
*(int*)state = ++index;
|
*(int*)state = ++index;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -298,8 +300,6 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
|
||||||
SpaFFMpegDec *this;
|
SpaFFMpegDec *this;
|
||||||
SpaFFMpegState *state;
|
SpaFFMpegState *state;
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
SpaFormat *f, *tf;
|
|
||||||
size_t fs;
|
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL)
|
if (node == NULL || node->handle == NULL || format == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
@ -316,22 +316,12 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
|
if ((res = spa_format_video_parse (format, &state->format[0]) < 0))
|
||||||
if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
return res;
|
||||||
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 (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||||
memcpy (tf, f, fs);
|
memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo));
|
||||||
state->current_format = tf;
|
state->current_format = &state->format[1].format;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ struct _FFMpegBuffer {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SpaVideoRawFormat raw_format[2];
|
SpaFormatVideo format[2];
|
||||||
SpaFormat *current_format;
|
SpaFormat *current_format;
|
||||||
bool have_buffers;
|
bool have_buffers;
|
||||||
FFMpegBuffer buffers[MAX_BUFFERS];
|
FFMpegBuffer buffers[MAX_BUFFERS];
|
||||||
|
|
@ -278,12 +278,14 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node,
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return SPA_RESULT_ENUM_END;
|
return SPA_RESULT_ENUM_END;
|
||||||
}
|
}
|
||||||
*format = &s->raw_format[0].format;
|
*format = &s->format[0].format;
|
||||||
*(int*)state = ++index;
|
*(int*)state = ++index;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -298,8 +300,6 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
|
||||||
SpaFFMpegEnc *this;
|
SpaFFMpegEnc *this;
|
||||||
SpaFFMpegState *state;
|
SpaFFMpegState *state;
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
SpaFormat *f, *tf;
|
|
||||||
size_t fs;
|
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL)
|
if (node == NULL || node->handle == NULL || format == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
@ -315,23 +315,16 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
|
||||||
state->current_format = NULL;
|
state->current_format = NULL;
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
if ((res = spa_format_video_parse (format, &state->format[0]) < 0))
|
||||||
|
return res;
|
||||||
|
|
||||||
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
|
if (format->media_type != SPA_MEDIA_TYPE_VIDEO ||
|
||||||
if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
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;
|
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||||
|
|
||||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||||
memcpy (tf, f, fs);
|
memcpy (&state->format[1], &state->format[0], sizeof (SpaFormatVideo));
|
||||||
state->current_format = tf;
|
state->current_format = &state->format[1].format;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
|
||||||
|
|
@ -88,12 +88,12 @@ enum {
|
||||||
|
|
||||||
static const SpaPropInfo prop_info[PROP_ID_LAST] =
|
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_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_INT, sizeof (int),
|
SPA_PROP_TYPE_INT, sizeof (int),
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaProxyProps, socketfd) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -626,10 +626,9 @@ spa_proxy_node_port_get_status (SpaNode *node,
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
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;
|
SpaControlCmdAddMem am;
|
||||||
SpaControlCmdAddBuffer ab;
|
|
||||||
int i;
|
int i;
|
||||||
SpaBuffer *b;
|
SpaBuffer *b;
|
||||||
SpaMemory *bmem;
|
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);
|
fprintf (stderr, "proxy %p: error invalid memory\n", this);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (mem->fd == -1) {
|
||||||
|
fprintf (stderr, "proxy %p: error memory without fd\n", this);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
am.port_id = port_id;
|
am.port_id = port_id;
|
||||||
am.mem = mem->mem;
|
am.mem = mem->mem;
|
||||||
|
|
@ -670,42 +673,10 @@ add_buffer (SpaProxy *this, SpaControlBuilder *builder, uint32_t port_id, SpaBuf
|
||||||
am.size = mem->size;
|
am.size = mem->size;
|
||||||
spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_ADD_MEM, &am);
|
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;
|
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
|
static SpaResult
|
||||||
spa_proxy_node_port_use_buffers (SpaNode *node,
|
spa_proxy_node_port_use_buffers (SpaNode *node,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
|
|
@ -720,6 +691,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
||||||
uint8_t buf[4096];
|
uint8_t buf[4096];
|
||||||
int fds[32];
|
int fds[32];
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
|
SpaControlCmdUseBuffers ub;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
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));
|
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) {
|
if (buffers == NULL || n_buffers == 0) {
|
||||||
port->buffers = NULL;
|
port->buffers = NULL;
|
||||||
port->n_buffers = 0;
|
port->n_buffers = 0;
|
||||||
|
|
@ -748,7 +717,12 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
||||||
port->n_buffers = n_buffers;
|
port->n_buffers = n_buffers;
|
||||||
}
|
}
|
||||||
for (i = 0; i < port->n_buffers; i++)
|
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);
|
spa_control_builder_end (&builder, &control);
|
||||||
|
|
||||||
|
|
@ -1044,9 +1018,7 @@ parse_control (SpaProxy *this,
|
||||||
break;
|
break;
|
||||||
case SPA_CONTROL_CMD_REMOVE_MEM:
|
case SPA_CONTROL_CMD_REMOVE_MEM:
|
||||||
break;
|
break;
|
||||||
case SPA_CONTROL_CMD_ADD_BUFFER:
|
case SPA_CONTROL_CMD_USE_BUFFERS:
|
||||||
break;
|
|
||||||
case SPA_CONTROL_CMD_REMOVE_BUFFER:
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
case SPA_CONTROL_CMD_PROCESS_BUFFER:
|
||||||
|
|
|
||||||
|
|
@ -140,24 +140,24 @@ enum {
|
||||||
|
|
||||||
static const SpaPropInfo prop_info[] =
|
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_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_STRING, 63,
|
SPA_PROP_TYPE_STRING, 63,
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaV4l2SourceProps, device) },
|
{ PROP_ID_DEVICE_NAME, offsetof (SpaV4l2SourceProps, device_name),
|
||||||
{ PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the device",
|
"device-name", "Human-readable name of the device",
|
||||||
SPA_PROP_FLAG_READABLE,
|
SPA_PROP_FLAG_READABLE,
|
||||||
SPA_PROP_TYPE_STRING, 127,
|
SPA_PROP_TYPE_STRING, 127,
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaV4l2SourceProps, device_name) },
|
{ PROP_ID_DEVICE_FD, offsetof (SpaV4l2SourceProps, device_fd),
|
||||||
{ PROP_ID_DEVICE_FD, "device-fd", "Device file descriptor",
|
"device-fd", "Device file descriptor",
|
||||||
SPA_PROP_FLAG_READABLE,
|
SPA_PROP_FLAG_READABLE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaV4l2SourceProps, device_fd) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
@ -357,15 +357,15 @@ spa_v4l2_format_init (V4l2Format *f)
|
||||||
f->fmt.props.n_prop_info = 3;
|
f->fmt.props.n_prop_info = 3;
|
||||||
f->fmt.props.prop_info = f->infos;
|
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,
|
SPA_PROP_ID_VIDEO_FORMAT,
|
||||||
offsetof (V4l2Format, 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,
|
SPA_PROP_ID_VIDEO_SIZE,
|
||||||
offsetof (V4l2Format, 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,
|
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||||
offsetof (V4l2Format, framerate));
|
offsetof (V4l2Format, framerate));
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
@ -386,7 +386,7 @@ spa_v4l2_source_node_port_enum_formats (SpaNode *node,
|
||||||
if (port_id != 0)
|
if (port_id != 0)
|
||||||
return SPA_RESULT_INVALID_PORT;
|
return SPA_RESULT_INVALID_PORT;
|
||||||
|
|
||||||
res = spa_v4l2_enum_format (this, format, state);
|
res = spa_v4l2_enum_format (this, format, filter, state);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -403,7 +403,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
|
||||||
V4l2Format *f, *tf;
|
V4l2Format *f, *tf;
|
||||||
size_t fs;
|
size_t fs;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL || format == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = (SpaV4l2Source *) node->handle;
|
this = (SpaV4l2Source *) node->handle;
|
||||||
|
|
@ -417,6 +417,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
|
||||||
spa_v4l2_clear_buffers (this);
|
spa_v4l2_clear_buffers (this);
|
||||||
spa_v4l2_close (this);
|
spa_v4l2_close (this);
|
||||||
state->current_format = NULL;
|
state->current_format = NULL;
|
||||||
|
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,28 +230,28 @@ static const FormatInfo format_info[] =
|
||||||
{ V4L2_PIX_FMT_SRGGB8, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_BAYER },
|
{ V4L2_PIX_FMT_SRGGB8, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_BAYER },
|
||||||
|
|
||||||
/* compressed formats */
|
/* compressed formats */
|
||||||
{V4L2_PIX_FMT_MJPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MJPG },
|
{ V4L2_PIX_FMT_MJPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MJPG },
|
||||||
{V4L2_PIX_FMT_JPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_IMAGE, SPA_MEDIA_SUBTYPE_JPEG },
|
{ V4L2_PIX_FMT_JPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_IMAGE, SPA_MEDIA_SUBTYPE_JPEG },
|
||||||
{V4L2_PIX_FMT_PJPG, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
{ V4L2_PIX_FMT_PJPG, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
||||||
{V4L2_PIX_FMT_DV, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_DV },
|
{ V4L2_PIX_FMT_DV, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_DV },
|
||||||
{V4L2_PIX_FMT_MPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEGTS },
|
{ V4L2_PIX_FMT_MPEG, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEGTS },
|
||||||
{V4L2_PIX_FMT_H264, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 },
|
{ V4L2_PIX_FMT_H264, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 },
|
||||||
{V4L2_PIX_FMT_H264_NO_SC, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 },
|
{ V4L2_PIX_FMT_H264_NO_SC, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 },
|
||||||
{V4L2_PIX_FMT_H264_MVC, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 },
|
{ V4L2_PIX_FMT_H264_MVC, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H264 },
|
||||||
{V4L2_PIX_FMT_H263, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H263 },
|
{ V4L2_PIX_FMT_H263, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_H263 },
|
||||||
{V4L2_PIX_FMT_MPEG1, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG1 },
|
{ V4L2_PIX_FMT_MPEG1, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG1 },
|
||||||
{V4L2_PIX_FMT_MPEG2, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG2 },
|
{ V4L2_PIX_FMT_MPEG2, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG2 },
|
||||||
{V4L2_PIX_FMT_MPEG4, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG4 },
|
{ V4L2_PIX_FMT_MPEG4, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_MPEG4 },
|
||||||
{V4L2_PIX_FMT_XVID, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_XVID },
|
{ V4L2_PIX_FMT_XVID, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_XVID },
|
||||||
{V4L2_PIX_FMT_VC1_ANNEX_G, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VC1 },
|
{ V4L2_PIX_FMT_VC1_ANNEX_G, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VC1 },
|
||||||
{V4L2_PIX_FMT_VC1_ANNEX_L, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VC1 },
|
{ V4L2_PIX_FMT_VC1_ANNEX_L, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VC1 },
|
||||||
{V4L2_PIX_FMT_VP8, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VP8 },
|
{ V4L2_PIX_FMT_VP8, SPA_VIDEO_FORMAT_ENCODED, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_VP8 },
|
||||||
|
|
||||||
/* Vendor-specific formats */
|
/* Vendor-specific formats */
|
||||||
{V4L2_PIX_FMT_WNVA, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
{ V4L2_PIX_FMT_WNVA, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
||||||
{V4L2_PIX_FMT_SN9C10X, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
{ V4L2_PIX_FMT_SN9C10X, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
||||||
{V4L2_PIX_FMT_PWC1, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
{ V4L2_PIX_FMT_PWC1, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
||||||
{V4L2_PIX_FMT_PWC2, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
{ V4L2_PIX_FMT_PWC2, SPA_VIDEO_FORMAT_UNKNOWN, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const FormatInfo *
|
static const FormatInfo *
|
||||||
|
|
@ -280,15 +280,33 @@ video_format_to_format_info (SpaVideoFormat format)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#define FOURCC_ARGS(f) (f)&0x7f,((f)>>8)&0x7f,((f)>>16)&0x7f,((f)>>24)&0x7f
|
||||||
|
|
||||||
static SpaResult
|
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];
|
SpaV4l2State *state = &this->state[0];
|
||||||
int res, i, pi;
|
int res, i, pi;
|
||||||
V4l2Format *fmt;
|
V4l2Format *fmt;
|
||||||
const FormatInfo *info;
|
const FormatInfo *info;
|
||||||
|
SpaVideoFormat video_format;
|
||||||
|
|
||||||
if (spa_v4l2_open (this) < 0)
|
if (spa_v4l2_open (this) < 0)
|
||||||
return SPA_RESULT_ERROR;
|
return SPA_RESULT_ERROR;
|
||||||
|
|
@ -306,15 +324,47 @@ spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, void **cookie)
|
||||||
*cookie = state;
|
*cookie = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
if (state->next_fmtdesc) {
|
if (state->next_fmtdesc) {
|
||||||
if ((res = xioctl (state->fd, VIDIOC_ENUM_FMT, &state->fmtdesc)) < 0) {
|
if (filter) {
|
||||||
if (errno != EINVAL)
|
SpaPropValue val;
|
||||||
perror ("VIDIOC_ENUM_FMT");
|
|
||||||
return SPA_RESULT_ENUM_END;
|
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->next_fmtdesc = false;
|
||||||
|
|
||||||
state->frmsize.index = 0;
|
state->frmsize.index = 0;
|
||||||
state->frmsize.pixel_format = state->fmtdesc.pixelformat;
|
state->frmsize.pixel_format = state->fmtdesc.pixelformat;
|
||||||
state->next_frmsize = true;
|
state->next_frmsize = true;
|
||||||
|
|
@ -354,23 +404,23 @@ again:
|
||||||
fmt->fmt.props.unset_mask = 0;
|
fmt->fmt.props.unset_mask = 0;
|
||||||
|
|
||||||
if (info->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
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,
|
SPA_PROP_ID_VIDEO_FORMAT,
|
||||||
offsetof (V4l2Format, format));
|
offsetof (V4l2Format, format));
|
||||||
fmt->format = info->format;
|
fmt->format = info->format;
|
||||||
pi = ++fmt->fmt.props.n_prop_info;
|
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,
|
SPA_PROP_ID_VIDEO_SIZE,
|
||||||
offsetof (V4l2Format, size));
|
offsetof (V4l2Format, size));
|
||||||
fmt->size.width = state->frmsize.discrete.width;
|
fmt->size.width = state->frmsize.discrete.width;
|
||||||
fmt->size.height = state->frmsize.discrete.height;
|
fmt->size.height = state->frmsize.discrete.height;
|
||||||
pi = ++fmt->fmt.props.n_prop_info;
|
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,
|
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||||
offsetof (V4l2Format, framerate));
|
offsetof (V4l2Format, framerate));
|
||||||
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
|
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
|
||||||
fmt->infos[pi].range_values = fmt->ranges;
|
fmt->infos[pi].range_values = fmt->ranges;
|
||||||
fmt->infos[pi].n_range_values = 0;
|
fmt->infos[pi].n_range_values = 0;
|
||||||
|
|
@ -417,21 +467,16 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
|
||||||
struct v4l2_format reqfmt, fmt;
|
struct v4l2_format reqfmt, fmt;
|
||||||
struct v4l2_streamparm streamparm;
|
struct v4l2_streamparm streamparm;
|
||||||
const FormatInfo *info = NULL;
|
const FormatInfo *info = NULL;
|
||||||
int i;
|
|
||||||
|
|
||||||
CLEAR (fmt);
|
CLEAR (fmt);
|
||||||
CLEAR (streamparm);
|
CLEAR (streamparm);
|
||||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
|
||||||
for (i = 0; i < SPA_N_ELEMENTS (format_info); i++) {
|
info = find_format_info_by_media_type (f->fmt.media_type,
|
||||||
if (format_info[i].media_type == f->fmt.media_type &&
|
f->fmt.media_subtype,
|
||||||
format_info[i].media_subtype == f->fmt.media_subtype &&
|
f->format,
|
||||||
format_info[i].format == f->format) {
|
0);
|
||||||
info = &format_info[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,18 +75,18 @@ enum {
|
||||||
|
|
||||||
static const SpaPropInfo prop_info[] =
|
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_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
SPA_PROP_TYPE_DOUBLE, sizeof (double),
|
||||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range,
|
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, volume_range,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVolumeProps, volume) },
|
{ PROP_ID_MUTE, offsetof (SpaVolumeProps, mute),
|
||||||
{ PROP_ID_MUTE, "mute", "Mute",
|
"mute", "Mute",
|
||||||
SPA_PROP_FLAG_READWRITE,
|
SPA_PROP_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_BOOL, sizeof (bool),
|
SPA_PROP_TYPE_BOOL, sizeof (bool),
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaVolumeProps, mute) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ struct _SpaXvSink {
|
||||||
SpaEventCallback event_cb;
|
SpaEventCallback event_cb;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
|
||||||
SpaVideoRawFormat raw_format[2];
|
SpaFormatVideo format[2];
|
||||||
SpaFormat *current_format;
|
SpaFormat *current_format;
|
||||||
|
|
||||||
SpaXvState state;
|
SpaXvState state;
|
||||||
|
|
@ -97,24 +97,24 @@ enum {
|
||||||
|
|
||||||
static const SpaPropInfo prop_info[] =
|
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_FLAG_READWRITE,
|
||||||
SPA_PROP_TYPE_STRING, 63,
|
SPA_PROP_TYPE_STRING, 63,
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaXvSinkProps, device) },
|
{ PROP_ID_DEVICE_NAME, offsetof (SpaXvSinkProps, device_name),
|
||||||
{ PROP_ID_DEVICE_NAME, "device-name", "Human-readable name of the device",
|
"device-name", "Human-readable name of the device",
|
||||||
SPA_PROP_FLAG_READABLE,
|
SPA_PROP_FLAG_READABLE,
|
||||||
SPA_PROP_TYPE_STRING, 127,
|
SPA_PROP_TYPE_STRING, 127,
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaXvSinkProps, device_name) },
|
{ PROP_ID_DEVICE_FD, offsetof (SpaXvSinkProps, device_fd),
|
||||||
{ PROP_ID_DEVICE_FD, "device-fd", "Device file descriptor",
|
"device-fd", "Device file descriptor",
|
||||||
SPA_PROP_FLAG_READABLE,
|
SPA_PROP_FLAG_READABLE,
|
||||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||||
NULL,
|
NULL },
|
||||||
offsetof (SpaXvSinkProps, device_fd) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
@ -308,12 +308,14 @@ spa_xv_sink_node_port_enum_formats (SpaNode *node,
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return SPA_RESULT_ENUM_END;
|
return SPA_RESULT_ENUM_END;
|
||||||
}
|
}
|
||||||
*format = &this->raw_format[0].format;
|
*format = &this->format[0].format;
|
||||||
*(int*)state = ++index;
|
*(int*)state = ++index;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
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_type == SPA_MEDIA_TYPE_VIDEO) {
|
||||||
if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
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;
|
return res;
|
||||||
|
|
||||||
f = &this->raw_format[0].format;
|
f = &this->format[0].format;
|
||||||
tf = &this->raw_format[1].format;
|
tf = &this->format[1].format;
|
||||||
fs = sizeof (SpaVideoRawFormat);
|
fs = sizeof (SpaVideoFormat);
|
||||||
} else
|
} else
|
||||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||||
} else
|
} else
|
||||||
|
|
|
||||||
|
|
@ -318,20 +318,20 @@ negotiate_formats (AppData *data)
|
||||||
f.fmt.props.n_prop_info = 3;
|
f.fmt.props.n_prop_info = 3;
|
||||||
f.fmt.props.prop_info = f.infos;
|
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,
|
SPA_PROP_ID_VIDEO_FORMAT,
|
||||||
offsetof (VideoFormat, format));
|
offsetof (VideoFormat, format));
|
||||||
f.format = SPA_VIDEO_FORMAT_YUY2;
|
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,
|
SPA_PROP_ID_VIDEO_SIZE,
|
||||||
offsetof (VideoFormat, size));
|
offsetof (VideoFormat, size));
|
||||||
f.size.width = 320;
|
f.size.width = 320;
|
||||||
f.size.height = 240;
|
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,
|
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||||
offsetof (VideoFormat, framerate));
|
offsetof (VideoFormat, framerate));
|
||||||
f.framerate.num = 25;
|
f.framerate.num = 25;
|
||||||
f.framerate.denom = 1;
|
f.framerate.denom = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue