Rework formats

Use a POD for the format body. This allows us to more easily build
and copy the formats.
Remove obsolete code to make video and audio formats.
Use SpaVideo/AudioInfo to keep track of formats. Make functions to parse
the format into the structures.
Update plugins
This commit is contained in:
Wim Taymans 2017-02-24 09:28:18 +01:00
parent 7fc73953cd
commit 16b62de53a
34 changed files with 1096 additions and 1579 deletions

View file

@ -330,6 +330,10 @@ spa_alsa_sink_node_port_enum_formats (SpaNode *node,
unsigned int index)
{
SpaALSASink *this;
SpaResult res;
SpaFormat *fmt;
uint8_t buffer[1024];
SpaPODBuilder b = { buffer, sizeof (buffer), };
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -341,19 +345,43 @@ spa_alsa_sink_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
SPA_MEDIA_SUBTYPE_RAW,
&this->query_format);
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
SPA_AUDIO_FORMAT_S16,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_ENUM, 2,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S32,
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
44100,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, INT32_MAX,
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
2,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, INT32_MAX,
0), SpaFormat);
break;
case 1:
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
SPA_MEDIA_SUBTYPE_AAC,
&this->query_format);
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_AAC,
0), SpaFormat);
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = &this->query_format.format;
b.data = this->format_buffer;
b.size = sizeof (this->format_buffer);
b.offset = 0;
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
return res;
*format = SPA_MEMBER (b.data, 0, SpaFormat);
return SPA_RESULT_OK;
}
@ -456,7 +484,7 @@ spa_alsa_sink_node_port_get_format (SpaNode *node,
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
*format = &this->current_format.format;
*format = NULL;
return SPA_RESULT_OK;
}

View file

@ -367,6 +367,9 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node,
{
SpaALSASource *this;
SpaResult res;
SpaFormat *fmt;
uint8_t buffer[256];
SpaPODBuilder b = { buffer, sizeof (buffer), };
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -378,23 +381,42 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
SPA_MEDIA_SUBTYPE_RAW,
&this->query_format);
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
SPA_AUDIO_FORMAT_S16,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_ENUM, 2,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S32,
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
44100,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, INT32_MAX,
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
2,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, INT32_MAX,
0), SpaFormat);
break;
case 1:
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
SPA_MEDIA_SUBTYPE_AAC,
&this->query_format);
break;
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_AAC,
0), SpaFormat);
default:
return SPA_RESULT_ENUM_END;
}
if ((res = spa_format_audio_filter (&this->query_format, filter)) != SPA_RESULT_OK)
b.data = this->format_buffer;
b.size = sizeof (this->format_buffer);
b.offset = 0;
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
return res;
*format = &this->query_format.format;
*format = SPA_MEMBER (this->format_buffer, 0, SpaFormat);
return SPA_RESULT_OK;
}
@ -502,7 +524,7 @@ spa_alsa_source_node_port_get_format (SpaNode *node,
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
*format = &this->current_format.format;
*format = NULL;
return SPA_RESULT_OK;
}

View file

@ -108,7 +108,7 @@ spa_alsa_format_to_alsa (SpaAudioFormat format)
}
int
spa_alsa_set_format (SpaALSAState *state, SpaFormatAudio *fmt, SpaPortFormatFlags flags)
spa_alsa_set_format (SpaALSAState *state, SpaAudioInfo *fmt, SpaPortFormatFlags flags)
{
unsigned int rrate, rchannels;
snd_pcm_uframes_t period_size;

View file

@ -35,6 +35,7 @@ extern "C" {
#include <spa/loop.h>
#include <spa/ringbuffer.h>
#include <spa/audio/format.h>
#include <spa/format-builder.h>
typedef struct _SpaALSAState SpaALSAState;
typedef struct _SpaALSABuffer SpaALSABuffer;
@ -89,8 +90,9 @@ struct _SpaALSAState {
snd_pcm_t *hndl;
bool have_format;
SpaFormatAudio query_format;
SpaFormatAudio current_format;
SpaAudioInfo current_format;
uint8_t format_buffer[1024];
snd_pcm_sframes_t buffer_frames;
snd_pcm_sframes_t period_frames;
snd_pcm_format_t format;
@ -125,7 +127,7 @@ struct _SpaALSAState {
};
int spa_alsa_set_format (SpaALSAState *state,
SpaFormatAudio *fmt,
SpaAudioInfo *info,
SpaPortFormatFlags flags);
SpaResult spa_alsa_start (SpaALSAState *state, bool xrun_recover);

View file

@ -51,7 +51,7 @@ struct _MixerBuffer {
typedef struct {
bool valid;
bool have_format;
SpaFormatAudio format[2];
SpaAudioInfo format;
SpaAudioMixerPortProps props[2];
SpaPortInfo info;
size_t buffer_index;
@ -328,14 +328,11 @@ spa_audiomixer_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
SPA_MEDIA_SUBTYPE_RAW,
&port->format[0]);
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = &port->format[0].format;
*format = NULL;
return SPA_RESULT_OK;
}
@ -366,7 +363,7 @@ spa_audiomixer_node_port_set_format (SpaNode *node,
return SPA_RESULT_OK;
}
if ((res = spa_format_audio_parse (format, &port->format[1])) < 0)
if ((res = spa_format_audio_parse (format, &port->format)) < 0)
return res;
port->have_format = true;
@ -396,7 +393,7 @@ spa_audiomixer_node_port_get_format (SpaNode *node,
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
*format = &port->format[1].format;
*format = NULL;
return SPA_RESULT_OK;
}

View file

@ -29,6 +29,7 @@
#include <spa/node.h>
#include <spa/list.h>
#include <spa/audio/format.h>
#include <spa/format-builder.h>
#include <lib/props.h>
#define SAMPLES_TO_TIME(this,s) ((s) * SPA_NSEC_PER_SEC / (this)->current_format.info.raw.rate)
@ -88,8 +89,8 @@ struct _SpaAudioTestSrc {
SpaPortOutput *output;
bool have_format;
SpaFormatAudio query_format;
SpaFormatAudio current_format;
SpaAudioInfo current_format;
uint8_t format_buffer[1024];
size_t bpf;
ATSBuffer buffers[MAX_BUFFERS];
@ -469,6 +470,9 @@ spa_audiotestsrc_node_port_enum_formats (SpaNode *node,
{
SpaAudioTestSrc *this;
SpaResult res;
SpaFormat *fmt;
uint8_t buffer[256];
SpaPODBuilder b = { buffer, sizeof (buffer), };
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -480,17 +484,40 @@ spa_audiotestsrc_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
SPA_MEDIA_SUBTYPE_RAW,
&this->query_format);
{
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
SPA_AUDIO_FORMAT_S16,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_ENUM, 2,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S32,
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
44100,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, INT32_MAX,
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
2,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, INT32_MAX,
0), SpaFormat);
break;
}
default:
return SPA_RESULT_ENUM_END;
}
if ((res = spa_format_audio_filter (&this->query_format, filter)) != SPA_RESULT_OK)
b.data = this->format_buffer;
b.size = sizeof (this->format_buffer);
b.offset = 0;
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
return res;
*format = &this->query_format.format;
*format = SPA_MEMBER (this->format_buffer, 0, SpaFormat);
return SPA_RESULT_OK;
}
@ -569,6 +596,7 @@ spa_audiotestsrc_node_port_get_format (SpaNode *node,
const SpaFormat **format)
{
SpaAudioTestSrc *this;
SpaPODBuilder b = { NULL, };
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -581,7 +609,21 @@ spa_audiotestsrc_node_port_get_format (SpaNode *node,
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
*format = &this->current_format.format;
b.data = this->format_buffer;
b.size = sizeof (this->format_buffer);
*format = SPA_MEMBER (b.data, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
this->current_format.info.raw.format,
SPA_POD_PROP_FLAG_READWRITE,
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
this->current_format.info.raw.rate,
SPA_POD_PROP_FLAG_READWRITE,
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
this->current_format.info.raw.channels,
SPA_POD_PROP_FLAG_READWRITE,
0), SpaFormat);
return SPA_RESULT_OK;
}

View file

@ -51,8 +51,9 @@ struct _FFMpegBuffer {
};
typedef struct {
SpaFormatVideo format[2];
SpaFormat *current_format;
bool have_format;
SpaVideoInfo query_format;
SpaVideoInfo current_format;
bool have_buffers;
FFMpegBuffer buffers[MAX_BUFFERS];
SpaPortInfo info;
@ -268,14 +269,11 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
SPA_MEDIA_SUBTYPE_RAW,
&port->format[0]);
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = &port->format[0].format;
*format = NULL;
return SPA_RESULT_OK;
}
@ -302,16 +300,16 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (format == NULL) {
port->current_format = NULL;
port->have_format = false;
return SPA_RESULT_OK;
}
if ((res = spa_format_video_parse (format, &port->format[0]) < 0))
if ((res = spa_format_video_parse (format, &port->query_format) < 0))
return res;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo));
port->current_format = &port->format[1].format;
memcpy (&port->current_format, &port->query_format, sizeof (SpaVideoInfo));
port->have_format = true;
}
return SPA_RESULT_OK;
@ -336,10 +334,10 @@ spa_ffmpeg_dec_node_port_get_format (SpaNode *node,
port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (port->current_format == NULL)
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
*format = port->current_format;
*format = NULL;
return SPA_RESULT_OK;
}
@ -476,7 +474,7 @@ spa_ffmpeg_dec_node_process_output (SpaNode *node)
if ((output = port->io) == NULL)
return SPA_RESULT_ERROR;
if (port->current_format == NULL) {
if (!port->have_format) {
output->status = SPA_RESULT_NO_FORMAT;
return SPA_RESULT_ERROR;
}

View file

@ -56,7 +56,7 @@ struct _FFMpegBuffer {
};
typedef struct {
SpaFormatVideo format[2];
SpaVideoInfo format[2];
SpaFormat *current_format;
bool have_buffers;
FFMpegBuffer buffers[MAX_BUFFERS];
@ -273,14 +273,11 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
SPA_MEDIA_SUBTYPE_RAW,
&port->format[0]);
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = &port->format[0].format;
*format = NULL;
return SPA_RESULT_OK;
}
@ -310,16 +307,17 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
port->current_format = NULL;
return SPA_RESULT_OK;
}
if ((res = spa_format_video_parse (format, &port->format[0]) < 0))
return res;
if (format->media_type != SPA_MEDIA_TYPE_VIDEO ||
format->media_subtype != SPA_MEDIA_SUBTYPE_RAW)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if ((res = spa_format_video_parse (format, &port->format[0]) < 0))
return res;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo));
port->current_format = &port->format[1].format;
memcpy (&port->format[1], &port->format[0], sizeof (SpaVideoInfo));
port->current_format = NULL;
}
return SPA_RESULT_OK;

View file

@ -30,6 +30,7 @@
#include <spa/log.h>
#include <spa/loop.h>
#include <spa/id-map.h>
#include <spa/format-builder.h>
#include <lib/debug.h>
#include <lib/props.h>
@ -63,23 +64,6 @@ struct _V4l2Buffer {
struct v4l2_buffer v4l2_buffer;
};
typedef struct _V4l2Format V4l2Format;
struct _V4l2Format {
SpaFormat fmt;
SpaVideoFormat format;
SpaRectangle size;
SpaFraction framerate;
SpaVideoInterlaceMode interlace_mode;
SpaVideoColorRange color_range;
SpaVideoColorMatrix color_matrix;
SpaVideoTransferFunction transfer_function;
SpaVideoColorPrimaries color_primaries;
SpaPropInfo infos[16];
SpaPropRangeInfo ranges[16];
SpaFraction framerates[16];
};
typedef struct {
uint32_t node;
uint32_t clock;
@ -99,8 +83,9 @@ typedef struct {
struct v4l2_frmsizeenum frmsize;
struct v4l2_frmivalenum frmival;
V4l2Format format[2];
V4l2Format *current_format;
bool have_format;
SpaVideoInfo current_format;
uint8_t format_buffer[1024];
int fd;
bool opened;
@ -357,7 +342,7 @@ spa_v4l2_source_node_send_command (SpaNode *node,
SpaV4l2State *state = &this->state[0];
SpaResult res;
if (state->current_format == NULL)
if (!state->have_format)
return SPA_RESULT_NO_FORMAT;
if (state->n_buffers == 0)
@ -380,7 +365,7 @@ spa_v4l2_source_node_send_command (SpaNode *node,
{
SpaV4l2State *state = &this->state[0];
if (state->current_format == NULL)
if (!state->have_format)
return SPA_RESULT_NO_FORMAT;
if (state->n_buffers == 0)
@ -483,28 +468,6 @@ spa_v4l2_source_node_remove_port (SpaNode *node,
return SPA_RESULT_NOT_IMPLEMENTED;
}
static SpaResult
spa_v4l2_format_init (V4l2Format *f, const SpaFormat *sf)
{
f->fmt.props.n_prop_info = 3;
f->fmt.props.prop_info = f->infos;
spa_prop_info_fill_video (&f->infos[0],
SPA_PROP_ID_VIDEO_FORMAT,
offsetof (V4l2Format, format));
spa_prop_info_fill_video (&f->infos[1],
SPA_PROP_ID_VIDEO_SIZE,
offsetof (V4l2Format, size));
spa_prop_info_fill_video (&f->infos[2],
SPA_PROP_ID_VIDEO_FRAMERATE,
offsetof (V4l2Format, framerate));
f->fmt.media_type = sf->media_type;
f->fmt.media_subtype = sf->media_subtype;
return spa_props_copy_values (&sf->props, &f->fmt.props);
}
static SpaResult
spa_v4l2_source_node_port_enum_formats (SpaNode *node,
SpaDirection direction,
@ -539,7 +502,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
SpaV4l2Source *this;
SpaV4l2State *state;
SpaResult res;
V4l2Format *f, *tf;
SpaVideoInfo info;
if (node == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -555,43 +518,34 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
spa_v4l2_stream_off (this);
spa_v4l2_clear_buffers (this);
spa_v4l2_close (this);
state->current_format = NULL;
state->have_format = false;
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}
f = &state->format[0];
tf = &state->format[1];
if ((SpaFormat*)f != format) {
if ((res = spa_v4l2_format_init (f, format)) < 0)
if ((res = spa_format_video_parse (format, &info)) < 0)
return res;
} else {
f = (V4l2Format*)format;
}
if (state->current_format) {
if (f->fmt.media_type == state->current_format->fmt.media_type &&
f->fmt.media_subtype == state->current_format->fmt.media_subtype &&
f->format == state->current_format->format &&
f->size.width == state->current_format->size.width &&
f->size.height == state->current_format->size.height)
if (state->have_format) {
if (info.media_type == state->current_format.media_type &&
info.media_subtype == state->current_format.media_subtype &&
info.info.raw.format == state->current_format.info.raw.format &&
info.info.raw.size.width == state->current_format.info.raw.size.width &&
info.info.raw.size.height == state->current_format.info.raw.size.height)
return SPA_RESULT_OK;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
spa_v4l2_use_buffers (this, NULL, 0);
state->current_format = NULL;
state->have_format = false;
}
}
if (spa_v4l2_set_format (this, f, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
if (spa_v4l2_set_format (this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
if ((res = spa_v4l2_format_init (tf, &f->fmt)) < 0)
return res;
state->current_format = tf;
state->current_format = info;
state->have_format = true;
update_state (this, SPA_NODE_STATE_READY);
}
@ -606,6 +560,7 @@ spa_v4l2_source_node_port_get_format (SpaNode *node,
{
SpaV4l2Source *this;
SpaV4l2State *state;
SpaPODBuilder b = { NULL, };
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -617,10 +572,26 @@ spa_v4l2_source_node_port_get_format (SpaNode *node,
state = &this->state[port_id];
if (state->current_format == NULL)
if (!state->have_format)
return SPA_RESULT_NO_FORMAT;
*format = &state->current_format->fmt;
b.data = state->format_buffer;
b.size = sizeof (state->format_buffer);
*format = SPA_MEMBER (b.data, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
state->current_format.info.raw.format,
SPA_POD_PROP_FLAG_READWRITE,
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE,
state->current_format.info.raw.size.width,
state->current_format.info.raw.size.height,
SPA_POD_PROP_FLAG_READWRITE,
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION,
state->current_format.info.raw.framerate.num,
state->current_format.info.raw.framerate.denom,
SPA_POD_PROP_FLAG_READWRITE,
0), SpaFormat);
return SPA_RESULT_OK;
}
@ -685,7 +656,7 @@ spa_v4l2_source_node_port_use_buffers (SpaNode *node,
state = &this->state[port_id];
if (state->current_format == NULL)
if (!state->have_format)
return SPA_RESULT_NO_FORMAT;
if (state->n_buffers) {
@ -728,7 +699,7 @@ spa_v4l2_source_node_port_alloc_buffers (SpaNode *node,
state = &this->state[port_id];
if (state->current_format == NULL)
if (!state->have_format)
return SPA_RESULT_NO_FORMAT;
res = spa_v4l2_alloc_buffers (this, params, n_params, buffers, n_buffers);
@ -1003,6 +974,7 @@ v4l2_source_init (const SpaHandleFactory *factory,
strncpy (this->props[1].device, str, 63);
this->props[1].props.unset_mask &= ~1;
}
this->props[1].props.unset_mask &= ~1;
update_state (this, SPA_NODE_STATE_CONFIGURE);

View file

@ -328,27 +328,25 @@ enum_filter_format (const SpaFormat *filter, unsigned int index)
if ((filter->media_type == SPA_MEDIA_TYPE_VIDEO || filter->media_type == SPA_MEDIA_TYPE_IMAGE)) {
if (filter->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
SpaPropValue val;
SpaResult res;
unsigned int idx;
const SpaPropInfo *pi;
SpaPODProp *p;
unsigned int n_values;
const uint32_t *values;
idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FORMAT);
if (idx == SPA_IDX_INVALID)
if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_FORMAT)))
return SPA_VIDEO_FORMAT_UNKNOWN;
pi = &filter->props.prop_info[idx];
if (pi->type != SPA_PROP_TYPE_UINT32)
if (p->body.value.type != SPA_PROP_TYPE_INT)
return SPA_VIDEO_FORMAT_UNKNOWN;
res = spa_props_get_value (&filter->props, idx, &val);
if (res >= 0) {
values = SPA_POD_BODY_CONST (&p->body.value);
n_values = SPA_POD_PROP_N_VALUES (p);
if (p->body.flags & SPA_POD_PROP_FLAG_UNSET) {
if (index + 1 < n_values)
video_format = values[index + 1];
} else {
if (index == 0)
video_format = *((SpaVideoFormat *)val.value);
} else if (res == SPA_RESULT_PROPERTY_UNSET) {
if (index < pi->n_range_values)
video_format = *((SpaVideoFormat *)pi->range_values[index].val.value);
video_format = values[0];
}
} else {
if (index == 0)
@ -453,9 +451,12 @@ spa_v4l2_enum_format (SpaV4l2Source *this,
unsigned int index)
{
SpaV4l2State *state = &this->state[0];
int res, i, pi;
V4l2Format *fmt;
int res;
const FormatInfo *info;
SpaPODFrame f[2];
SpaPODProp *prop;
SpaFormat *fmt;
SpaPODBuilder b = { state->format_buffer, sizeof (state->format_buffer), };
if (spa_v4l2_open (this) < 0)
return SPA_RESULT_ERROR;
@ -506,37 +507,30 @@ next_fmtdesc:
state->frmsize.pixel_format = state->fmtdesc.pixelformat;
state->next_frmsize = true;
}
if (!(info = fourcc_to_format_info (state->fmtdesc.pixelformat)))
goto next_fmtdesc;
next_frmsize:
while (state->next_frmsize) {
if (filter) {
const SpaPropInfo *pi;
unsigned int idx;
SpaPropValue val;
SpaResult res;
SpaPODProp *p;
/* check if we have a fixed frame size */
idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_SIZE);
if (idx == SPA_IDX_INVALID)
if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_SIZE)))
goto do_frmsize;
pi = &filter->props.prop_info[idx];
if (pi->type != SPA_PROP_TYPE_RECTANGLE)
if (p->body.value.type != SPA_PROP_TYPE_RECTANGLE)
return SPA_RESULT_ENUM_END;
res = spa_props_get_value (&filter->props, idx, &val);
if (res >= 0) {
const SpaRectangle *size = val.value;
if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) {
const SpaRectangle *values = SPA_POD_BODY_CONST (&p->body.value);
if (state->frmsize.index > 0)
goto next_fmtdesc;
state->frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE;
state->frmsize.discrete.width = size->width;
state->frmsize.discrete.height = size->height;
state->frmsize.discrete.width = values[0].width;
state->frmsize.discrete.height = values[0].height;
goto have_size;
}
}
@ -549,33 +543,33 @@ do_frmsize:
return SPA_RESULT_ENUM_END;
}
if (filter) {
const SpaPropInfo *pi;
unsigned int idx;
const SpaRectangle step = { 1, 1 };
SpaPODProp *p;
const SpaRectangle step = { 1, 1 }, *values;
uint32_t range;
unsigned int i, n_values;
/* check if we have a fixed frame size */
idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_SIZE);
if (idx == SPA_IDX_INVALID)
if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_SIZE)))
goto have_size;
/* checked above */
pi = &filter->props.prop_info[idx];
range = p->body.flags & SPA_POD_PROP_RANGE_MASK;
values = SPA_POD_BODY_CONST (&p->body.value);
n_values = SPA_POD_PROP_N_VALUES (p);
if (pi->range_type == SPA_PROP_RANGE_TYPE_MIN_MAX) {
if (filter_framesize (&state->frmsize, pi->range_values[0].val.value,
pi->range_values[1].val.value,
if (range == SPA_POD_PROP_RANGE_MIN_MAX && n_values > 2) {
if (filter_framesize (&state->frmsize, &values[1],
&values[2],
&step))
goto have_size;
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_STEP) {
if (filter_framesize (&state->frmsize, pi->range_values[0].val.value,
pi->range_values[1].val.value,
pi->range_values[2].val.value))
} else if (range == SPA_PROP_RANGE_TYPE_STEP && n_values > 3) {
if (filter_framesize (&state->frmsize, &values[1],
&values[2],
&values[3]))
goto have_size;
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_ENUM) {
unsigned int i;
for (i = 0; i < pi->n_range_values; i++) {
if (filter_framesize (&state->frmsize, pi->range_values[i].val.value,
pi->range_values[i].val.value,
} else if (range == SPA_PROP_RANGE_TYPE_ENUM) {
for (i = 1; i < n_values; i++) {
if (filter_framesize (&state->frmsize, &values[i],
&values[i],
&step))
goto have_size;
}
@ -608,43 +602,44 @@ have_size:
}
}
fmt = &state->format[0];
fmt->fmt.media_type = info->media_type;
fmt->fmt.media_subtype = info->media_subtype;
fmt->fmt.props.prop_info = fmt->infos;
fmt->fmt.props.n_prop_info = pi = 0;
fmt->fmt.props.unset_mask = 0;
fmt = SPA_MEMBER (b.data,
spa_pod_builder_push_format (&b, &f[0],
info->media_type,
info->media_subtype),
SpaFormat);
if (info->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
spa_prop_info_fill_video (&fmt->infos[pi],
SPA_PROP_ID_VIDEO_FORMAT,
offsetof (V4l2Format, format));
fmt->format = info->format;
pi = ++fmt->fmt.props.n_prop_info;
} else {
fmt->format = info->format;
spa_pod_builder_format_prop (&b,
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
info->format,
SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READWRITE,
0);
}
spa_prop_info_fill_video (&fmt->infos[pi],
SPA_PROP_ID_VIDEO_SIZE,
offsetof (V4l2Format, size));
fmt->size.width = state->frmsize.discrete.width;
fmt->size.height = state->frmsize.discrete.height;
pi = ++fmt->fmt.props.n_prop_info;
spa_pod_builder_format_prop (&b,
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE,
state->frmsize.discrete.width,
state->frmsize.discrete.height,
SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READWRITE,
0);
spa_prop_info_fill_video (&fmt->infos[pi],
SPA_PROP_ID_VIDEO_FRAMERATE,
offsetof (V4l2Format, framerate));
fmt->infos[pi].range_values = fmt->ranges;
fmt->infos[pi].n_range_values = 0;
i = state->frmival.index = 0;
prop = SPA_MEMBER (b.data,
spa_pod_builder_push_prop (&b, &f[1],
SPA_PROP_ID_VIDEO_FRAMERATE,
SPA_POD_PROP_RANGE_NONE |
SPA_POD_PROP_FLAG_UNSET |
SPA_POD_PROP_FLAG_READWRITE),
SpaPODProp);
spa_pod_builder_fraction (&b, 25, 1);
state->frmival.index = 0;
while (true) {
if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMEINTERVALS, &state->frmival)) < 0) {
if (errno == EINVAL) {
state->frmsize.index++;
state->next_frmsize = true;
if (i == 0)
if (state->frmival.index == 0)
goto next_frmsize;
break;
}
@ -652,42 +647,40 @@ have_size:
return SPA_RESULT_ENUM_END;
}
if (filter) {
SpaPropValue val;
const SpaPropInfo *pi;
unsigned int idx;
SpaResult res;
const SpaFraction step = { 1, 1 };
SpaPODProp *p;
uint32_t range;
unsigned int i, n_values;
const SpaFraction step = { 1, 1 }, *values;
/* check against filter */
idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FRAMERATE);
if (idx == SPA_IDX_INVALID)
if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_FRAMERATE)))
goto have_framerate;
pi = &filter->props.prop_info[idx];
if (pi->type != SPA_PROP_TYPE_FRACTION)
if (p->body.value.type != SPA_PROP_TYPE_FRACTION)
return SPA_RESULT_ENUM_END;
res = spa_props_get_value (&filter->props, idx, &val);
if (res == 0) {
if (filter_framerate (&state->frmival, val.value,
val.value,
range = p->body.flags & SPA_POD_PROP_RANGE_MASK;
values = SPA_POD_BODY_CONST (&p->body.value);
n_values = SPA_POD_PROP_N_VALUES (p);
if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) {
if (filter_framerate (&state->frmival, &values[0],
&values[0],
&step))
goto have_framerate;
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_MIN_MAX) {
if (filter_framerate (&state->frmival, pi->range_values[0].val.value,
pi->range_values[1].val.value,
} else if (range == SPA_PROP_RANGE_TYPE_MIN_MAX && n_values > 2) {
if (filter_framerate (&state->frmival, &values[1],
&values[2],
&step))
goto have_framerate;
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_STEP) {
if (filter_framerate (&state->frmival, pi->range_values[0].val.value,
pi->range_values[1].val.value,
pi->range_values[2].val.value))
} else if (range == SPA_PROP_RANGE_TYPE_STEP && n_values > 3) {
if (filter_framerate (&state->frmival, &values[1],
&values[2],
&values[3]))
goto have_framerate;
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_ENUM) {
unsigned int i;
for (i = 0; i < pi->n_range_values; i++) {
if (filter_framerate (&state->frmival, pi->range_values[i].val.value,
pi->range_values[i].val.value,
} else if (range == SPA_PROP_RANGE_TYPE_ENUM) {
for (i = 1; i < n_values; i++) {
if (filter_framerate (&state->frmival, &values[i],
&values[i],
&step))
goto have_framerate;
}
@ -697,55 +690,43 @@ have_size:
}
have_framerate:
fmt->ranges[i].name = NULL;
if (state->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
fmt->framerates[i].num = state->frmival.discrete.denominator;
fmt->framerates[i].denom = state->frmival.discrete.numerator;
fmt->ranges[i].val.size = sizeof (SpaFraction);
fmt->ranges[i].val.value = &fmt->framerates[i];
i++;
prop->body.flags |= SPA_PROP_RANGE_TYPE_ENUM;
spa_pod_builder_fraction (&b,
state->frmival.discrete.denominator,
state->frmival.discrete.numerator);
state->frmival.index++;
if (i == 16)
break;
} else if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
state->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
fmt->framerates[0].num = state->frmival.stepwise.min.denominator;
fmt->framerates[0].denom = state->frmival.stepwise.min.numerator;
fmt->ranges[0].val.size = sizeof (SpaFraction);
fmt->ranges[0].val.value = &fmt->framerates[0];
fmt->framerates[1].num = state->frmival.stepwise.max.denominator;
fmt->framerates[1].denom = state->frmival.stepwise.max.numerator;
fmt->ranges[1].val.size = sizeof (SpaFraction);
fmt->ranges[1].val.value = &fmt->framerates[1];
spa_pod_builder_fraction (&b,
state->frmival.stepwise.min.denominator,
state->frmival.stepwise.min.numerator);
spa_pod_builder_fraction (&b,
state->frmival.stepwise.max.denominator,
state->frmival.stepwise.max.numerator);
if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_MIN_MAX;
i = 2;
prop->body.flags |= SPA_PROP_RANGE_TYPE_MIN_MAX;
} else {
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_STEP;
fmt->framerates[2].num = state->frmival.stepwise.step.denominator;
fmt->framerates[2].denom = state->frmival.stepwise.step.numerator;
fmt->ranges[2].val.size = sizeof (SpaFraction);
fmt->ranges[2].val.value = &fmt->framerates[2];
i = 3;
prop->body.flags |= SPA_PROP_RANGE_TYPE_STEP;
spa_pod_builder_fraction (&b,
state->frmival.stepwise.step.denominator,
state->frmival.stepwise.step.numerator);
}
break;
}
}
fmt->infos[pi].n_range_values = i;
fmt->framerate = fmt->framerates[0];
if (i > 1) {
SPA_PROPS_INDEX_UNSET (&fmt->fmt.props, pi);
}
pi = ++fmt->fmt.props.n_prop_info;
spa_pod_builder_pop (&b, &f[1]);
spa_pod_builder_pop (&b, &f[0]);
*format = &state->format[0].fmt;
*format = fmt;
return SPA_RESULT_OK;
}
static int
spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
spa_v4l2_set_format (SpaV4l2Source *this, SpaVideoInfo *f, bool try_only)
{
SpaV4l2State *state = &this->state[0];
int cmd;
@ -758,27 +739,27 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
info = find_format_info_by_media_type (f->fmt.media_type,
f->fmt.media_subtype,
f->format,
info = find_format_info_by_media_type (f->media_type,
f->media_subtype,
f->info.raw.format,
0);
if (info == NULL) {
spa_log_error (state->log, "v4l2: unknown media type %d %d %d", f->fmt.media_type,
f->fmt.media_subtype, f->format);
spa_log_error (state->log, "v4l2: unknown media type %d %d %d", f->media_type,
f->media_subtype, f->info.raw.format);
return -1;
}
fmt.fmt.pix.pixelformat = info->fourcc;
fmt.fmt.pix.field = V4L2_FIELD_ANY;
fmt.fmt.pix.width = f->size.width;
fmt.fmt.pix.height = f->size.height;
streamparm.parm.capture.timeperframe.numerator = f->framerate.denom;
streamparm.parm.capture.timeperframe.denominator = f->framerate.num;
fmt.fmt.pix.width = f->info.raw.size.width;
fmt.fmt.pix.height = f->info.raw.size.height;
streamparm.parm.capture.timeperframe.numerator = f->info.raw.framerate.denom;
streamparm.parm.capture.timeperframe.denominator = f->info.raw.framerate.num;
spa_log_info (state->log, "v4l2: set %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat,
fmt.fmt.pix.width, fmt.fmt.pix.height,
streamparm.parm.capture.timeperframe.numerator,
streamparm.parm.capture.timeperframe.denominator);
streamparm.parm.capture.timeperframe.denominator,
streamparm.parm.capture.timeperframe.numerator);
reqfmt = fmt;
@ -797,8 +778,8 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
spa_log_info (state->log, "v4l2: got %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat,
fmt.fmt.pix.width, fmt.fmt.pix.height,
streamparm.parm.capture.timeperframe.numerator,
streamparm.parm.capture.timeperframe.denominator);
streamparm.parm.capture.timeperframe.denominator,
streamparm.parm.capture.timeperframe.numerator);
if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat ||
reqfmt.fmt.pix.width != fmt.fmt.pix.width ||
@ -808,6 +789,11 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
if (try_only)
return 0;
f->info.raw.size.width = fmt.fmt.pix.width;
f->info.raw.size.height = fmt.fmt.pix.height;
f->info.raw.framerate.num = streamparm.parm.capture.timeperframe.denominator;
f->info.raw.framerate.denom = streamparm.parm.capture.timeperframe.numerator;
state->fmt = fmt;
state->info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS |
SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |

View file

@ -141,11 +141,11 @@ drawing_data_init (DrawingData *dd,
SpaVideoTestSrc *this,
char* data)
{
SpaFormatVideo *format = &this->current_format;
SpaVideoInfo *format = &this->current_format;
SpaRectangle *size = &format->info.raw.size;
if (format->format.media_type != SPA_MEDIA_TYPE_VIDEO ||
format->format.media_subtype != SPA_MEDIA_SUBTYPE_RAW)
if ((format->media_type != SPA_MEDIA_TYPE_VIDEO) ||
(format->media_subtype != SPA_MEDIA_SUBTYPE_RAW))
return SPA_RESULT_NOT_IMPLEMENTED;
switch (format->info.raw.format) {

View file

@ -30,6 +30,7 @@
#include <spa/node.h>
#include <spa/list.h>
#include <spa/video/format.h>
#include <spa/format-builder.h>
#include <lib/props.h>
#define FRAMES_TO_TIME(this,f) ((this->current_format.info.raw.framerate.denom * (f) * SPA_NSEC_PER_SEC) / \
@ -86,8 +87,8 @@ struct _SpaVideoTestSrc {
SpaPortOutput *output;
bool have_format;
SpaFormatVideo query_format;
SpaFormatVideo current_format;
SpaVideoInfo current_format;
uint8_t format_buffer[1024];
size_t bpp;
VTSBuffer buffers[MAX_BUFFERS];
@ -430,6 +431,8 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node,
SpaVideoTestSrc *this;
SpaResult res;
SpaFormat *fmt;
uint8_t buffer[1024];
SpaPODBuilder b = { buffer, sizeof (buffer), };
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -441,36 +444,39 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
{
int idx;
static const uint32_t format_values[] = {
SPA_VIDEO_FORMAT_RGB,
SPA_VIDEO_FORMAT_UYVY,
};
static const SpaPropRangeInfo format_range[] = {
{ "RGB", { sizeof (uint32_t), &format_values[0] } },
{ "UYVY", { sizeof (uint32_t), &format_values[1] } },
};
SpaPropInfo *info;
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
SPA_MEDIA_SUBTYPE_RAW,
&this->query_format);
idx = spa_props_index_for_id (&this->query_format.format.props, SPA_PROP_ID_VIDEO_FORMAT);
info = (SpaPropInfo *) &this->query_format.format.props.prop_info[idx];
info->n_range_values = SPA_N_ELEMENTS (format_range);
info->range_values = format_range;
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
SPA_VIDEO_FORMAT_RGB,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_ENUM, 2,
SPA_VIDEO_FORMAT_RGB,
SPA_VIDEO_FORMAT_UYVY,
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE,
320, 240,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, 1,
INT32_MAX, INT32_MAX,
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, 25, 1,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
0, 1,
INT32_MAX, 1,
0), SpaFormat);
break;
}
default:
return SPA_RESULT_ENUM_END;
}
if ((res = spa_format_filter (&this->query_format.format, filter, &fmt)) != SPA_RESULT_OK)
b.data = this->format_buffer;
b.size = sizeof (this->format_buffer);
b.offset = 0;
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
return res;
*format = fmt;
*format = SPA_MEMBER (this->format_buffer, 0, SpaFormat);
return SPA_RESULT_OK;
}
@ -561,6 +567,7 @@ spa_videotestsrc_node_port_get_format (SpaNode *node,
const SpaFormat **format)
{
SpaVideoTestSrc *this;
SpaPODBuilder b = { NULL, };
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -573,7 +580,24 @@ spa_videotestsrc_node_port_get_format (SpaNode *node,
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
*format = &this->current_format.format;
b.data = this->format_buffer;
b.size = sizeof (this->format_buffer);
*format = SPA_MEMBER (b.data, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
this->current_format.info.raw.format,
SPA_POD_PROP_FLAG_READWRITE,
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE,
this->current_format.info.raw.size.width,
this->current_format.info.raw.size.height,
SPA_POD_PROP_FLAG_READWRITE,
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION,
this->current_format.info.raw.framerate.num,
this->current_format.info.raw.framerate.denom,
SPA_POD_PROP_FLAG_READWRITE,
0), SpaFormat);
return SPA_RESULT_OK;
}

View file

@ -25,6 +25,7 @@
#include <spa/node.h>
#include <spa/list.h>
#include <spa/audio/format.h>
#include <spa/format-builder.h>
#include <lib/props.h>
#define MAX_BUFFERS 16
@ -79,8 +80,7 @@ struct _SpaVolume {
SpaNodeEventCallback event_cb;
void *user_data;
SpaFormatAudio query_format;
SpaFormatAudio current_format;
SpaAudioInfo current_format;
SpaVolumePort in_ports[1];
SpaVolumePort out_ports[1];
@ -291,6 +291,10 @@ spa_volume_node_port_enum_formats (SpaNode *node,
unsigned int index)
{
SpaVolume *this;
SpaResult res;
SpaFormat *fmt;
uint8_t buffer[1024];
SpaPODBuilder b = { buffer, sizeof (buffer), };
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -302,14 +306,34 @@ spa_volume_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
SPA_MEDIA_SUBTYPE_RAW,
&this->query_format);
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
SPA_AUDIO_FORMAT_S16,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_ENUM, 2,
SPA_AUDIO_FORMAT_S16,
SPA_AUDIO_FORMAT_S32,
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
44100,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, INT32_MAX,
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
2,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
SPA_POD_PROP_RANGE_MIN_MAX,
1, INT32_MAX,
0), SpaFormat);
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = &this->query_format.format;
if ((res = spa_format_filter (fmt, filter, NULL)) != SPA_RESULT_OK)
return res;
*format = NULL;
return SPA_RESULT_OK;
}
@ -405,7 +429,7 @@ spa_volume_node_port_get_format (SpaNode *node,
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
*format = &this->current_format.format;
*format = NULL;
return SPA_RESULT_OK;
}

View file

@ -87,8 +87,8 @@ struct _SpaXvSink {
SpaNodeEventCallback event_cb;
void *user_data;
SpaFormatVideo format[2];
SpaFormat *current_format;
bool have_format;
SpaVideoInfo current_format;
SpaPortInfo info;
SpaXvState state;
@ -304,14 +304,11 @@ spa_xv_sink_node_port_enum_formats (SpaNode *node,
switch (index) {
case 0:
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
SPA_MEDIA_SUBTYPE_RAW,
&this->format[0]);
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = &this->format[0].format;
*format = NULL;
return SPA_RESULT_OK;
}
@ -325,8 +322,7 @@ spa_xv_sink_node_port_set_format (SpaNode *node,
{
SpaXvSink *this;
SpaResult res;
SpaFormat *f, *tf;
size_t fs;
SpaVideoInfo info;
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -337,29 +333,25 @@ spa_xv_sink_node_port_set_format (SpaNode *node,
return SPA_RESULT_INVALID_PORT;
if (format == NULL) {
this->current_format = NULL;
this->have_format = false;
return SPA_RESULT_OK;
}
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
if ((res = spa_format_video_parse (format, &this->format[0]) < 0))
if ((res = spa_format_video_parse (format, &info) < 0))
return res;
f = &this->format[0].format;
tf = &this->format[1].format;
fs = sizeof (SpaVideoFormat);
} else
return SPA_RESULT_INVALID_MEDIA_TYPE;
} else
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (spa_xv_set_format (this, f, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
if (spa_xv_set_format (this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
memcpy (tf, f, fs);
this->current_format = tf;
this->current_format = info;
this->have_format = true;
}
return SPA_RESULT_OK;
@ -381,10 +373,10 @@ spa_xv_sink_node_port_get_format (SpaNode *node,
if (!CHECK_PORT (this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
if (this->current_format == NULL)
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
*format = this->current_format;
*format = NULL;
return SPA_RESULT_OK;
}

View file

@ -23,7 +23,7 @@ spa_xv_open (SpaXvSink *this)
}
static int
spa_xv_set_format (SpaXvSink *this, SpaFormat *format, bool try_only)
spa_xv_set_format (SpaXvSink *this, SpaVideoInfo *info, bool try_only)
{
if (spa_xv_open (this) < 0)
return -1;