diff options
author | Alfred E. Heggestad <aeh@db.org> | 2016-01-31 20:52:50 +0100 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2016-01-31 20:52:50 +0100 |
commit | 40132ce37490d1fdf67dc43ade729ceec31e42b0 (patch) | |
tree | 0c085127c7badc2a2b2e34d8859f200e7ef08832 | |
parent | c1bf762f56cc7234567aedae2791373c512dccc0 (diff) |
v4l2_codec: add list of encoders (fixes #99)
-rw-r--r-- | modules/v4l2_codec/v4l2_codec.c | 155 |
1 files changed, 92 insertions, 63 deletions
diff --git a/modules/v4l2_codec/v4l2_codec.c b/modules/v4l2_codec/v4l2_codec.c index 10206cf..c6e76e0 100644 --- a/modules/v4l2_codec/v4l2_codec.c +++ b/modules/v4l2_codec/v4l2_codec.c @@ -41,33 +41,29 @@ struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ - /* empty */ -}; -struct videnc_state { - struct videnc_param encprm; uint8_t *buffer; size_t buffer_len; int fd; - videnc_packet_h *pkth; - void *arg; struct { unsigned n_key; unsigned n_delta; } stats; }; +struct videnc_state { + struct le le; + struct videnc_param encprm; + videnc_packet_h *pkth; + void *arg; +}; + /* TODO: global data, move to per vidsrc instance */ static struct { - char device[256]; - unsigned width; - unsigned height; -} v4l2 = { - "/dev/video0", - 320, - 240 -}; + /* List of encoder-states (struct videnc_state) */ + struct list encoderl; +} v4l2; static struct vidsrc *vidsrc; @@ -84,7 +80,7 @@ static int xioctl(int fd, unsigned long int request, void *arg) } -static int print_caps(int fd) +static int print_caps(int fd, unsigned width, unsigned height) { struct v4l2_capability caps; struct v4l2_fmtdesc fmtdesc; @@ -147,8 +143,8 @@ static int print_caps(int fd) } fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = v4l2.width; - fmt.fmt.pix.height = v4l2.height; + fmt.fmt.pix.width = width; + fmt.fmt.pix.height = height; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_H264; fmt.fmt.pix.field = V4L2_FIELD_NONE; @@ -173,7 +169,7 @@ static int print_caps(int fd) } -static int init_mmap(struct videnc_state *st, int fd) +static int init_mmap(struct vidsrc_st *st, int fd) { struct v4l2_requestbuffers req; struct v4l2_buffer buf; @@ -270,27 +266,30 @@ static void enc_destructor(void *arg) { struct videnc_state *st = arg; - if (st->fd >=0 ) { - info("v4l2_codec: encoder stats" - " (keyframes:%u, deltaframes:%u)\n", - st->stats.n_key, st->stats.n_delta); - } + list_unlink(&st->le); +} - stop_capturing(st->fd); - if (st->buffer) - munmap(st->buffer, st->buffer_len); +static void encoders_read(const uint8_t *buf, size_t sz) +{ + struct le *le; + int err; - if (st->fd >= 0) { - fd_close(st->fd); - close(st->fd); + for (le = v4l2.encoderl.head; le; le = le->next) { + struct videnc_state *st = le->data; + + err = h264_packetize(buf, sz, + st->encprm.pktsize, st->pkth, st->arg); + if (err) { + warning("h264_packetize error (%m)\n", err); + } } } static void read_handler(int flags, void *arg) { - struct videnc_state *st = arg; + struct vidsrc_st *st = arg; struct v4l2_buffer buf; int err; (void)flags; @@ -333,46 +332,29 @@ static void read_handler(int flags, void *arg) } } - err = h264_packetize(st->buffer, buf.bytesused, - st->encprm.pktsize, st->pkth, st->arg); - if (err) { - warning("h264_packetize error (%m)\n", err); - } + /* pass the frame to the encoders */ + encoders_read(st->buffer, buf.bytesused); query_buffer(st->fd); } -static int encode_update(struct videnc_state **vesp, const struct vidcodec *vc, - struct videnc_param *prm, const char *fmtp, - videnc_packet_h *pkth, void *arg) +static int open_encoder(struct vidsrc_st *st, const char *device, + unsigned width, unsigned height) { - struct videnc_state *st; - int err = 0; - (void)fmtp; - - if (!vesp || !vc || !prm || !pkth) - return EINVAL; - - if (*vesp) - return 0; - - st = mem_zalloc(sizeof(*st), enc_destructor); - if (!st) - return ENOMEM; + int err; - st->encprm = *prm; - st->pkth = pkth; - st->arg = arg; + debug("v4l2_codec: opening video-encoder device (device=%s)\n", + device); - st->fd = open(v4l2.device, O_RDWR); + st->fd = open(device, O_RDWR); if (st->fd == -1) { err = errno; warning("Opening video device (%m)\n", err); goto out; } - err = print_caps(st->fd); + err = print_caps(st->fd, width, height); if (err) goto out; @@ -392,10 +374,38 @@ static int encode_update(struct videnc_state **vesp, const struct vidcodec *vc, if (err) goto out; +out: + return err; +} + + +static int encode_update(struct videnc_state **vesp, const struct vidcodec *vc, + struct videnc_param *prm, const char *fmtp, + videnc_packet_h *pkth, void *arg) +{ + struct videnc_state *st; + int err = 0; + (void)fmtp; + + if (!vesp || !vc || !prm || !pkth) + return EINVAL; + + if (*vesp) + return 0; + + st = mem_zalloc(sizeof(*st), enc_destructor); + if (!st) + return ENOMEM; + + st->encprm = *prm; + st->pkth = pkth; + st->arg = arg; + + list_append(&v4l2.encoderl, &st->le, st); + info("v4l2_codec: video encoder %s: %d fps, %d bit/s, pktsize=%u\n", vc->name, prm->fps, prm->bitrate, prm->pktsize); - out: if (err) mem_deref(st); else @@ -463,7 +473,22 @@ static bool h264_fmtp_cmp(const char *fmtp1, const char *fmtp2, void *data) static void src_destructor(void *arg) { struct vidsrc_st *st = arg; - (void)st; + + if (st->fd >=0 ) { + info("v4l2_codec: encoder stats" + " (keyframes:%u, deltaframes:%u)\n", + st->stats.n_key, st->stats.n_delta); + } + + stop_capturing(st->fd); + + if (st->buffer) + munmap(st->buffer, st->buffer_len); + + if (st->fd >= 0) { + fd_close(st->fd); + close(st->fd); + } } @@ -485,18 +510,22 @@ static int src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, if (!stp || !size || !frameh) return EINVAL; + if (str_isset(dev)) + dev = "/dev/video0"; + + debug("v4l2_codec: video-source alloc (device=%s)\n", dev); + st = mem_zalloc(sizeof(*st), src_destructor); if (!st) return ENOMEM; st->vs = vs; - /* NOTE: copy instance data into global space */ - if (str_isset(dev)) - str_ncpy(v4l2.device, dev, sizeof(v4l2.device)); - v4l2.width = size->w; - v4l2.height = size->h; + err = open_encoder(st, dev, size->w, size->h); + if (err) + goto out; +out: if (err) mem_deref(st); else |