Mercurial > libavformat.hg
changeset 1793:951d219ab67b libavformat
Pass the v4l2 buffer into the AVPacket, instead of allocating a new buffer
and copying the frame into it (remove a memcpy())
author | lucabe |
---|---|
date | Wed, 14 Feb 2007 13:25:24 +0000 |
parents | 662780b00ceb |
children | 11c57b75bccd |
files | v4l2.c |
diffstat | 1 files changed, 50 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/v4l2.c Wed Feb 14 11:23:11 2007 +0000 +++ b/v4l2.c Wed Feb 14 13:25:24 2007 +0000 @@ -59,6 +59,11 @@ unsigned int *buf_len; }; +struct buff_data { + int index; + int fd; +}; + struct fmt_map { enum PixelFormat ff_fmt; int32_t v4l2_fmt; @@ -293,10 +298,32 @@ return -1; } -static int mmap_read_frame(AVFormatContext *ctx, void *frame, int64_t *ts) +static void mmap_release_buffer(AVPacket *pkt) +{ + struct v4l2_buffer buf; + int res, fd; + struct buff_data *buf_descriptor = pkt->priv; + + memset(&buf, 0, sizeof(struct v4l2_buffer)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = buf_descriptor->index; + fd = buf_descriptor->fd; + av_free(buf_descriptor); + + res = ioctl (fd, VIDIOC_QBUF, &buf); + if (res < 0) { + av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n"); + } + pkt->data = NULL; + pkt->size = 0; +} + +static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) { struct video_data *s = ctx->priv_data; struct v4l2_buffer buf; + struct buff_data *buf_descriptor; int res; memset(&buf, 0, sizeof(struct v4l2_buffer)); @@ -319,20 +346,28 @@ } /* Image is at s->buff_start[buf.index] */ - memcpy(frame, s->buf_start[buf.index], buf.bytesused); - *ts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec; - - res = ioctl (s->fd, VIDIOC_QBUF, &buf); - if (res < 0) { - av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n"); + pkt->data= s->buf_start[buf.index]; + pkt->size = buf.bytesused; + pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec; + pkt->destruct = mmap_release_buffer; + buf_descriptor = av_malloc(sizeof(struct buff_data)); + if (buf_descriptor == NULL) { + /* Something went wrong... Since av_malloc() failed, we cannot even + * allocate a buffer for memcopying into it + */ + av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n"); + res = ioctl (s->fd, VIDIOC_QBUF, &buf); return -1; } + buf_descriptor->fd = s->fd; + buf_descriptor->index = buf.index; + pkt->priv = buf_descriptor; return s->buf_len[buf.index]; } -static int read_frame(AVFormatContext *ctx, void *frame, int64_t *ts) +static int read_frame(AVFormatContext *ctx, AVPacket *pkt) { return -1; } @@ -500,13 +535,14 @@ struct video_data *s = s1->priv_data; int res; - if (av_new_packet(pkt, s->frame_size) < 0) - return AVERROR_IO; + if (s->io_method == io_mmap) { + av_init_packet(pkt); + res = mmap_read_frame(s1, pkt); + } else if (s->io_method == io_read) { + if (av_new_packet(pkt, s->frame_size) < 0) + return AVERROR_IO; - if (s->io_method == io_mmap) { - res = mmap_read_frame(s1, pkt->data, &pkt->pts); - } else if (s->io_method == io_read) { - res = read_frame(s1, pkt->data, &pkt->pts); + res = read_frame(s1, pkt); } else { return AVERROR_IO; }