v4l2: work on format enumeration

Start work on format enumeration
fix fd leak in v4l2-source
Improve spa-inspect output
This commit is contained in:
Wim Taymans 2016-07-15 13:20:20 +02:00
parent 61caf0e19c
commit 77bc2a1793
6 changed files with 282 additions and 84 deletions

View file

@ -62,26 +62,40 @@ struct _V4l2Buffer {
};
typedef struct {
bool export_buf;
bool have_buffers;
bool next_fmtdesc;
struct v4l2_fmtdesc fmtdesc;
bool next_frmsize;
struct v4l2_frmsizeenum frmsize;
bool next_frmival;
struct v4l2_frmivalenum frmival;
void *cookie;
SpaVideoRawFormat raw_format[2];
SpaFormat *current_format;
bool opened;
bool have_buffers;
int fd;
bool opened;
struct v4l2_capability cap;
struct v4l2_format fmt;
enum v4l2_buf_type type;
enum v4l2_memory memtype;
struct v4l2_requestbuffers reqbuf;
V4l2Buffer buffers[MAX_BUFFERS];
V4l2Buffer *ready;
uint32_t ready_count;
SpaPollFd fds[1];
SpaPollItem poll;
SpaPortInfo info;
SpaAllocParam *params[1];
SpaAllocParamBuffers param_buffers;
bool export_buf;
SpaPortStatus status;
} SpaV4l2State;
struct _SpaV4l2Source {
@ -312,16 +326,18 @@ spa_v4l2_source_node_port_enum_formats (SpaHandle *handle,
state = &this->state[port_id];
/*
switch (index) {
case 0:
spa_video_raw_format_init (&state->raw_format[0]);
break;
default:
return SPA_RESULT_ENUM_END;
break;
}
*format = &state->raw_format[0].format;
*/
return SPA_RESULT_OK;
return spa_v4l2_enum_format (this, format, &state->cookie);
}
static SpaResult

View file

@ -256,6 +256,112 @@ video_format_to_fourcc (SpaVideoFormat format)
return fourcc;
}
#define FOURCC_ARGS(f) (f)&0x7f,((f)>>8)&0x7f,((f)>>16)&0x7f,((f)>>24)&0x7f
static SpaResult
spa_v4l2_enum_format (SpaV4l2Source *this, SpaFormat **format, void **cookie)
{
SpaV4l2State *state = &this->state[0];
int res;
if (spa_v4l2_open (this) < 0)
return SPA_RESULT_ERROR;
*format = NULL;
if (*cookie == NULL) {
CLEAR (state->fmtdesc);
state->fmtdesc.index = 0;
state->fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
state->next_fmtdesc = true;
CLEAR (state->frmsize);
state->next_frmsize = true;
CLEAR (state->frmival);
state->next_frmival = true;
*cookie = state;
}
again:
if (state->next_fmtdesc) {
if ((res = xioctl (state->fd, VIDIOC_ENUM_FMT, &state->fmtdesc)) < 0) {
if (errno != EINVAL)
perror ("VIDIOC_ENUM_FMT");
return SPA_RESULT_ENUM_END;
}
state->next_fmtdesc = false;
state->frmsize.index = 0;
state->frmsize.pixel_format = state->fmtdesc.pixelformat;
state->next_frmsize = true;
}
if (state->next_frmsize) {
if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMESIZES, &state->frmsize)) < 0) {
if (errno == EINVAL) {
state->fmtdesc.index++;
state->next_fmtdesc = true;
goto again;
}
perror ("VIDIOC_ENUM_FRAMESIZES");
return SPA_RESULT_ENUM_END;
}
state->next_frmsize = false;
if (state->frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
state->frmival.index = 0;
state->frmival.pixel_format = state->frmsize.pixel_format;
state->frmival.width = state->frmsize.discrete.width;
state->frmival.height = state->frmsize.discrete.height;
state->next_frmival = true;
}
}
if (state->next_frmival) {
if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMEINTERVALS, &state->frmival)) < 0) {
if (errno == EINVAL) {
state->frmsize.index++;
state->next_frmsize = true;
goto again;
}
perror ("VIDIOC_ENUM_FRAMEINTERVALS");
return SPA_RESULT_ENUM_END;
}
state->frmival.index++;
}
fprintf (stderr, "format %c%c%c%c\n", FOURCC_ARGS (state->fmtdesc.pixelformat));
if (state->frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
fprintf (stderr, "size %dx%d\n", state->frmsize.discrete.width, state->frmsize.discrete.height);
} else if (state->frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
fprintf (stderr, "size %dx%d - %dx%d with step %d/%d\n",
state->frmsize.stepwise.min_width,
state->frmsize.stepwise.min_height,
state->frmsize.stepwise.max_width,
state->frmsize.stepwise.max_height,
state->frmsize.stepwise.step_width,
state->frmsize.stepwise.step_height);
}
if (state->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
fprintf (stderr, "framerate %u/%u\n",
state->frmival.discrete.numerator,
state->frmival.discrete.denominator);
} else if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
fprintf (stderr, "framerate %u/%u - %u/%u\n",
state->frmival.stepwise.min.numerator,
state->frmival.stepwise.min.denominator,
state->frmival.stepwise.max.numerator,
state->frmival.stepwise.max.denominator);
} else if (state->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
fprintf (stderr, "framerate %u/%u - %u/%u step %u/%u\n",
state->frmival.stepwise.min.numerator,
state->frmival.stepwise.min.denominator,
state->frmival.stepwise.max.numerator,
state->frmival.stepwise.max.denominator,
state->frmival.stepwise.step.numerator,
state->frmival.stepwise.step.denominator);
}
return SPA_RESULT_OK;
}
static int
spa_v4l2_set_format (SpaV4l2Source *this, SpaFormat *format, bool try_only)
@ -493,6 +599,8 @@ mmap_init (SpaV4l2Source *this)
fprintf (stderr, "can't allocate enough buffers\n");
return -1;
}
if (state->export_buf)
fprintf (stderr, "using EXPBUF\n");
state->reqbuf = reqbuf;