From 9e374641d25e6d42a5f3043ae9d5359c6a0c704f Mon Sep 17 00:00:00 2001 From: Trever Fischer Date: Wed, 6 Jan 2010 10:41:32 -0500 Subject: Preliminary support for v4l2. It's ugly and works half the time, but it's there. --HG-- branch : v4l --- src/input/input_v4l2.c | 361 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 src/input/input_v4l2.c (limited to 'src') diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c new file mode 100644 index 000000000..aea947478 --- /dev/null +++ b/src/input/input_v4l2.c @@ -0,0 +1,361 @@ +#define LOG_MODULE "v4l2" +#define LOG + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + void *start; + size_t length; +} buffer_data; + +typedef struct { + int width; + int height; +} resolution_t; + +typedef struct { + buffer_data *buffers; + int bufcount; + resolution_t resolution; + int headerSent; +} v4l2_video_t; + +typedef struct { + buffer_data *buffers; + int bufcount; +} v4l2_radio_t; + +typedef struct { + input_plugin_t input_plugin; + + int fd; + char* mrl; + struct v4l2_capability cap; + xine_stream_t *stream; + + xine_event_queue_t *events; + v4l2_video_t* video; + v4l2_radio_t* radio; +} v4l2_input_plugin_t; + +void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx); +void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *input); +int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this); + + +int v4l2_input_open(input_plugin_t *this_gen) { + v4l2_input_plugin_t *this = (v4l2_input_plugin_t*) this_gen; + lprintf("Opening %s\n", this->mrl); + if ((this->fd = v4l2_open(this->mrl, O_RDWR))) { + /* TODO: Clean up this mess */ + this->events = xine_event_new_queue(this->stream); + v4l2_ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); + if (this->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { + this->video = malloc(sizeof(v4l2_video_t)); + this->video->headerSent = 0; + this->video->bufcount = 0; + } + if (this->cap.capabilities & V4L2_CAP_STREAMING) { + lprintf("Supports streaming. Allocating buffers...\n"); + if (this->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { + if (v4l2_input_setup_video_streaming(this)) { + lprintf("Video streaming ready.\n"); + return 1; + } else { + /* TODO: Fallbacks */ + lprintf("Video streaming setup failed.\n"); + return 0; + } + } else { + /* TODO: Radio streaming */ + lprintf("Sorry, only video is supported for now.\n"); + return 0; + } + } else { + lprintf("Device doesn't support streaming. Prod the author to support the other methods.\n"); + return 0; + } + } else { + return 0; + } +} + +int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { + this->video->bufcount = 0; + struct v4l2_requestbuffers reqbuf; + unsigned int i; + memset(&reqbuf, 0, sizeof(reqbuf)); + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = V4L2_MEMORY_MMAP; + reqbuf.count = 25; + + if (-1 == v4l2_ioctl(this->fd, VIDIOC_REQBUFS, &reqbuf)) { + lprintf("Buffer request failed. Is streaming supported?\n"); + return 0; + } + + this->video->bufcount = reqbuf.count; + lprintf("Got %i buffers for stremaing.\n", reqbuf.count); + + this->video->buffers = calloc(this->video->bufcount, sizeof(buffer_data)); + _x_assert(this->video->buffers); + for (i = 0;i < this->video->bufcount;i++) { + struct v4l2_buffer buffer; + memset(&buffer, 0, sizeof(buffer)); + buffer.type = reqbuf.type; + buffer.memory = reqbuf.memory; + buffer.index = i; + + if (-1 == v4l2_ioctl(this->fd, VIDIOC_QUERYBUF, &buffer)) { + lprintf("Couldn't allocate buffer %i\n", i); + return 0; + } + + this->video->buffers[i].length = buffer.length; + this->video->buffers[i].start = (void*)v4l2_mmap(NULL, buffer.length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + this->fd, buffer.m.offset); + if (MAP_FAILED == this->video->buffers[i].start) { + lprintf("Couldn't mmap buffer %i\n", i); + int j; + for(j = 0;jvideo->buffers[i].start, this->video->buffers[i].length); + } + free(this->video->buffers); + this->video->bufcount = 0; + return 0; + } + v4l2_input_enqueue_video_buffer(this, i); + } + + struct v4l2_format fmt; + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + /* TODO: Other formats? MPEG support? */ + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + v4l2_ioctl(this->fd, VIDIOC_S_FMT, &fmt); + this->video->resolution.width = fmt.fmt.pix.width; + this->video->resolution.height = fmt.fmt.pix.height; + if (-1 == v4l2_ioctl(this->fd, VIDIOC_STREAMON, &reqbuf.type)) { + lprintf("Couldn't start streaming: %s\n", strerror(errno)); + return 0; + } + return 1; +} + +buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t len) { + lprintf("Reading block\n"); + v4l2_input_plugin_t *this = (v4l2_input_plugin_t*)this_gen; + buf_element_t *buf = fifo->buffer_pool_alloc(fifo); + struct timeval tv; + xine_monotonic_clock(&tv, NULL); + buf->pts = (int64_t) tv.tv_sec * 90000 + (int64_t) tv.tv_usec * 9 / 100; + if (!this->video->headerSent) { + lprintf("Sending video header\n"); + xine_bmiheader bih; + bih.biSize = sizeof(xine_bmiheader); + bih.biWidth = this->video->resolution.width*2; + bih.biHeight = this->video->resolution.height*2; + lprintf("Getting size of %ix%i\n", this->video->resolution.width, this->video->resolution.height); + buf->size = sizeof(xine_bmiheader); + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_START; + memcpy(buf->content, &bih, sizeof(xine_bmiheader)); + this->video->headerSent = 1; + buf->type = BUF_VIDEO_YUY2; + } else { + lprintf("Sending video frame\n"); + /* TODO: Add audio support */ + v4l2_input_dequeue_video_buffer(this, buf); + this->video->headerSent = 0; + } + return buf; +} + +uint32_t v4l2_input_blocksize(input_plugin_t *this_gen) { + /* HACK */ + return 0; + v4l2_input_plugin_t *this = (v4l2_input_plugin_t*)this_gen; + if (this->video->headerSent) { + lprintf("Returning block size of %i\n",this->video->buffers[0].length); + return this->video->buffers[0].length; + } else { + lprintf("Returning block size of %i\n",sizeof(xine_bmiheader)); + return sizeof(xine_bmiheader); + } +} + +void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *output) { + struct v4l2_buffer buf; + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + output->content = output->mem; + v4l2_ioctl(this->fd, VIDIOC_DQBUF, &buf); + output->decoder_flags = BUF_FLAG_FRAME_START|BUF_FLAG_FRAME_END; + xine_fast_memcpy(output->content, this->video->buffers[buf.index].start, this->video->buffers[buf.index].length); + output->type = BUF_VIDEO_YUY2; + v4l2_input_enqueue_video_buffer(this, buf.index); +} + +void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx) { + struct v4l2_buffer buf; + memset(&buf, 0, sizeof(buf)); + buf.index = idx; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + v4l2_ioctl(this->fd, VIDIOC_QBUF, &buf); +} + +void v4l2_input_dispose(input_plugin_t *this_gen) { + lprintf("Disposing of myself.\n"); + v4l2_input_plugin_t* this = (v4l2_input_plugin_t*)this_gen; + + if (this->video != NULL) { + int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == v4l2_ioctl(this->fd, VIDIOC_STREAMOFF, &type)) { + lprintf("Couldn't stop streaming. Uh oh.\n"); + } + if (this->video->bufcount > 0) { + int i; + for(i = 0;ivideo->bufcount;i++) { + v4l2_munmap(this->video->buffers[i].start, this->video->buffers[i].length); + } + free(this->video->buffers); + } + free(this->video); + } + v4l2_close(this->fd); + free(this->mrl); + free(this); +} + +off_t v4l2_input_read(input_plugin_t *this_gen, char *buf, off_t nlen) { + /* Only block reads are supported. */ + return 0; +} + +uint32_t v4l2_input_get_capabilities(input_plugin_t* this_gen) { + return INPUT_CAP_BLOCK; +} + +const char* v4l2_input_get_mrl(input_plugin_t* this_gen) { + v4l2_input_plugin_t* this = (v4l2_input_plugin_t*)this_gen; + /* HACK HACK HACK HACK */ + /* So far, the only way to get the yuv_frames demuxer to work with this */ + return "v4l:/"; + //return this->mrl; +} + +int v4l2_input_get_optional_data(input_plugin_t *this_gen, void *data, int data_type) { + return INPUT_OPTIONAL_UNSUPPORTED; +} + +/* Seeking not supported. */ +off_t v4l2_input_seek(input_plugin_t *this_gen, off_t offset, int origin) { + return -1; +} + +off_t v4l2_input_seek_time(input_plugin_t *this_gen, int time_offset, int origin) { + return -1; +} + +off_t v4l2_input_pos(input_plugin_t *this_gen) { + /* TODO */ + return 0; +} + +int v4l2_input_time(input_plugin_t *this_gen) { + /* TODO */ + return 0; +} + +off_t v4l2_input_length(input_plugin_t *this_gen) { + return -1; +} + +typedef struct { + input_class_t input_class; +} v4l2_input_class_t; + +static input_plugin_t *v4l2_class_get_instance(input_class_t *gen_cls, xine_stream_t *stream, const char *mrl) { + v4l2_input_plugin_t *this; + /* TODO: Radio devices */ + /* FIXME: Don't require devices to be of /dev/videoXXX */ + if (strncmp(mrl, "/dev/video", strlen("/dev/video")) != 0) + return NULL; + lprintf("We can handle %s!\n", mrl); + + this = calloc(1, sizeof(v4l2_input_plugin_t)); + _x_assert(this); + this->mrl = strdup(mrl); + this->input_plugin.open = v4l2_input_open; + this->input_plugin.get_capabilities = v4l2_input_get_capabilities; + this->input_plugin.get_blocksize = v4l2_input_blocksize; + this->input_plugin.get_mrl = v4l2_input_get_mrl; + this->input_plugin.dispose = v4l2_input_dispose; + this->input_plugin.read = v4l2_input_read; + this->input_plugin.read_block = v4l2_input_read_block; + this->input_plugin.seek = v4l2_input_seek; + this->input_plugin.seek_time = v4l2_input_seek_time; + this->input_plugin.get_current_pos = v4l2_input_pos; + this->input_plugin.get_current_time = v4l2_input_time; + this->input_plugin.get_length = v4l2_input_length; + this->input_plugin.get_optional_data = v4l2_input_get_optional_data; + this->input_plugin.input_class = gen_cls; + this->stream = stream; + + this->video = NULL; + this->radio = NULL; + lprintf("Ready to read!\n"); + + return &this->input_plugin; +} + +static const char *v4l2_class_get_description(input_class_t *this_gen) { + /* TODO: Translatable with _() */ + return "v4l2 input plugin"; +} + +static const char *v4l2_class_get_identifier(input_class_t *this_gen) { + return "v4l2"; +} + +static void v4l2_class_dispose(input_class_t *this_gen) { + free(this_gen); +} + +static void *v4l2_init_class(xine_t *xine, void *data) { + v4l2_input_class_t *this; + this = malloc(sizeof(v4l2_input_class_t)); + this->input_class.get_instance = v4l2_class_get_instance; + this->input_class.get_description = v4l2_class_get_description; + this->input_class.get_identifier = v4l2_class_get_identifier; + this->input_class.get_dir = NULL; + this->input_class.get_autoplay_list = NULL; + this->input_class.dispose = v4l2_class_dispose; + this->input_class.eject_media = NULL; + return &this->input_class; +} + +const input_info_t input_info_v4l2 = { + 4000 +}; + +const plugin_info_t xine_plugin_info[] = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_INPUT, 17, "v4l2", XINE_VERSION_CODE, &input_info_v4l2, v4l2_init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; \ No newline at end of file -- cgit v1.2.3 From 3f9216613e552ebf915fcf25496a62b252ab2100 Mon Sep 17 00:00:00 2001 From: Trever Fischer Date: Wed, 6 Jan 2010 12:22:48 -0500 Subject: Use libv4l only if available, add copyright header --HG-- branch : v4l --- src/input/input_v4l2.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index aea947478..20cf4f8b6 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -1,4 +1,32 @@ +/* +* Copyright (C) 2010 the xine project +* Copyright (C) 2010 Trever Fischer +* +* This file is part of xine, a free video player. +* +* xine is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* xine 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA +* +* v4l2 input plugin +*/ + #define LOG_MODULE "v4l2" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG #include @@ -12,9 +40,13 @@ #include #include #include -#include #include +#ifdef HAVE_LIBV4L2_H +#include +#else +#include +#endif typedef struct { void *start; size_t length; @@ -58,10 +90,19 @@ int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this); int v4l2_input_open(input_plugin_t *this_gen) { v4l2_input_plugin_t *this = (v4l2_input_plugin_t*) this_gen; lprintf("Opening %s\n", this->mrl); - if ((this->fd = v4l2_open(this->mrl, O_RDWR))) { +#ifdef HAVE_LIBV4L2_H + this->fd = v4l2_open(this->mrl, O_RDWR); +#else + this->fd = open(this->mrl, O_RDWR); +#endif + if (this->fd) { /* TODO: Clean up this mess */ this->events = xine_event_new_queue(this->stream); +#ifdef HAVE_LIBV4L2_H v4l2_ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); +#else + ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); +#endif if (this->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { this->video = malloc(sizeof(v4l2_video_t)); this->video->headerSent = 0; @@ -101,7 +142,11 @@ int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { reqbuf.memory = V4L2_MEMORY_MMAP; reqbuf.count = 25; +#ifdef HAVE_LIBV4L2_H if (-1 == v4l2_ioctl(this->fd, VIDIOC_REQBUFS, &reqbuf)) { +#else + if (-1 == ioctl(this->fd, VIDIOC_REQBUFS, &reqbuf)) { +#endif lprintf("Buffer request failed. Is streaming supported?\n"); return 0; } @@ -118,21 +163,36 @@ int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { buffer.memory = reqbuf.memory; buffer.index = i; +#ifdef HAVE_LIBV4L2_H if (-1 == v4l2_ioctl(this->fd, VIDIOC_QUERYBUF, &buffer)) { +#else + if (-1 == ioctl(this->fd, VIDIOC_QUERYBUF, &buffer)) { +#endif lprintf("Couldn't allocate buffer %i\n", i); return 0; } this->video->buffers[i].length = buffer.length; +#ifdef HAVE_LIBV4L2_H this->video->buffers[i].start = (void*)v4l2_mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, this->fd, buffer.m.offset); +#else + this->video->buffers[i].start = (void*)mmap(NULL, buffer.length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + this->fd, buffer.m.offset); +#endif if (MAP_FAILED == this->video->buffers[i].start) { lprintf("Couldn't mmap buffer %i\n", i); int j; for(j = 0;jvideo->buffers[i].start, this->video->buffers[i].length); +#else + munmap(this->video->buffers[i].start, this->video->buffers[i].length); +#endif } free(this->video->buffers); this->video->bufcount = 0; @@ -146,10 +206,18 @@ int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* TODO: Other formats? MPEG support? */ fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; +#ifdef HAVE_LIBV4L2_H v4l2_ioctl(this->fd, VIDIOC_S_FMT, &fmt); +#else + ioctl(this->fd, VIDIOC_S_FMT, &fmt); +#endif this->video->resolution.width = fmt.fmt.pix.width; this->video->resolution.height = fmt.fmt.pix.height; +#ifdef HAVE_LIBV4L2_H if (-1 == v4l2_ioctl(this->fd, VIDIOC_STREAMON, &reqbuf.type)) { +#else + if (-1 == ioctl(this->fd, VIDIOC_STREAMON, &reqbuf.type)) { +#endif lprintf("Couldn't start streaming: %s\n", strerror(errno)); return 0; } @@ -167,6 +235,7 @@ buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffer_t *fi lprintf("Sending video header\n"); xine_bmiheader bih; bih.biSize = sizeof(xine_bmiheader); + /* HACK: Why do I need to do this and why is it magic? */ bih.biWidth = this->video->resolution.width*2; bih.biHeight = this->video->resolution.height*2; lprintf("Getting size of %ix%i\n", this->video->resolution.width, this->video->resolution.height); @@ -203,7 +272,11 @@ void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *o buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; output->content = output->mem; +#ifdef HAVE_LIBV4L2_H v4l2_ioctl(this->fd, VIDIOC_DQBUF, &buf); +#else + ioctl(this->fd, VIDIOC_DQBUF, &buf); +#endif output->decoder_flags = BUF_FLAG_FRAME_START|BUF_FLAG_FRAME_END; xine_fast_memcpy(output->content, this->video->buffers[buf.index].start, this->video->buffers[buf.index].length); output->type = BUF_VIDEO_YUY2; @@ -216,7 +289,11 @@ void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx) { buf.index = idx; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; +#ifdef HAVE_LIBV4L2_H v4l2_ioctl(this->fd, VIDIOC_QBUF, &buf); +#else + ioctl(this->fd, VIDIOC_QBUF, &buf); +#endif } void v4l2_input_dispose(input_plugin_t *this_gen) { @@ -225,19 +302,31 @@ void v4l2_input_dispose(input_plugin_t *this_gen) { if (this->video != NULL) { int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +#ifdef HAVE_LIBV4L2_H if (-1 == v4l2_ioctl(this->fd, VIDIOC_STREAMOFF, &type)) { +#else + if (-1 == ioctl(this->fd, VIDIOC_STREAMOFF, &type)) { +#endif lprintf("Couldn't stop streaming. Uh oh.\n"); } if (this->video->bufcount > 0) { int i; for(i = 0;ivideo->bufcount;i++) { +#ifdef HAVE_LIBV4L2_H v4l2_munmap(this->video->buffers[i].start, this->video->buffers[i].length); +#else + munmap(this->video->buffers[i].start, this->video->buffers[i].length); +#endif } free(this->video->buffers); } free(this->video); } +#ifdef HAVE_LIBV4L2_H v4l2_close(this->fd); +#else + close(this->fd); +#endif free(this->mrl); free(this); } @@ -358,4 +447,4 @@ const plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT, 17, "v4l2", XINE_VERSION_CODE, &input_info_v4l2, v4l2_init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; \ No newline at end of file +}; -- cgit v1.2.3 From 935fedb922307d3f63f786f5f489eda248679831 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 21 Jan 2010 01:30:48 +0000 Subject: Tidy up the v4l2 plugin. Get rid of most compile-time warnings. Clean up white space. Mark xine_plugin_info as EXPORTED. Fix xine-lib internal #includes. Use #defines instead of many "#ifdef HAVE_LIBV4L2"/"#else"/"#endif". --HG-- branch : v4l --- src/input/input_v4l2.c | 132 ++++++++++++++++--------------------------------- 1 file changed, 42 insertions(+), 90 deletions(-) (limited to 'src') diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index 20cf4f8b6..1e6da1e78 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -29,9 +29,9 @@ #define LOG -#include -#include -#include +#include "input_plugin.h" +#include "xine_plugin.h" +#include "xine_internal.h" #include #include @@ -43,10 +43,17 @@ #include #ifdef HAVE_LIBV4L2_H -#include +# include #else -#include +# include +# include +# define v4l2_open(f,d) open(f,d) +# define v4l2_ioctl(f,c,a) ioctl(f,c,a) +# define v4l2_mmap(p,l,d,m,f,o) mmap(p,l,d,m,f,o) +# define v4l2_munmap(s,l) munmap(s,l) +# define v4l2_close(f) close(f) #endif + typedef struct { void *start; size_t length; @@ -82,27 +89,19 @@ typedef struct { v4l2_radio_t* radio; } v4l2_input_plugin_t; -void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx); -void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *input); -int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this); +static void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx); +static void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *input); +static int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this); -int v4l2_input_open(input_plugin_t *this_gen) { +static int v4l2_input_open(input_plugin_t *this_gen) { v4l2_input_plugin_t *this = (v4l2_input_plugin_t*) this_gen; lprintf("Opening %s\n", this->mrl); -#ifdef HAVE_LIBV4L2_H this->fd = v4l2_open(this->mrl, O_RDWR); -#else - this->fd = open(this->mrl, O_RDWR); -#endif if (this->fd) { /* TODO: Clean up this mess */ this->events = xine_event_new_queue(this->stream); -#ifdef HAVE_LIBV4L2_H v4l2_ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); -#else - ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); -#endif if (this->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { this->video = malloc(sizeof(v4l2_video_t)); this->video->headerSent = 0; @@ -133,7 +132,7 @@ int v4l2_input_open(input_plugin_t *this_gen) { } } -int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { +static int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { this->video->bufcount = 0; struct v4l2_requestbuffers reqbuf; unsigned int i; @@ -142,18 +141,14 @@ int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { reqbuf.memory = V4L2_MEMORY_MMAP; reqbuf.count = 25; -#ifdef HAVE_LIBV4L2_H if (-1 == v4l2_ioctl(this->fd, VIDIOC_REQBUFS, &reqbuf)) { -#else - if (-1 == ioctl(this->fd, VIDIOC_REQBUFS, &reqbuf)) { -#endif lprintf("Buffer request failed. Is streaming supported?\n"); return 0; } - + this->video->bufcount = reqbuf.count; lprintf("Got %i buffers for stremaing.\n", reqbuf.count); - + this->video->buffers = calloc(this->video->bufcount, sizeof(buffer_data)); _x_assert(this->video->buffers); for (i = 0;i < this->video->bufcount;i++) { @@ -162,37 +157,22 @@ int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { buffer.type = reqbuf.type; buffer.memory = reqbuf.memory; buffer.index = i; - -#ifdef HAVE_LIBV4L2_H + if (-1 == v4l2_ioctl(this->fd, VIDIOC_QUERYBUF, &buffer)) { -#else - if (-1 == ioctl(this->fd, VIDIOC_QUERYBUF, &buffer)) { -#endif lprintf("Couldn't allocate buffer %i\n", i); return 0; } - + this->video->buffers[i].length = buffer.length; -#ifdef HAVE_LIBV4L2_H this->video->buffers[i].start = (void*)v4l2_mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, this->fd, buffer.m.offset); -#else - this->video->buffers[i].start = (void*)mmap(NULL, buffer.length, - PROT_READ | PROT_WRITE, - MAP_SHARED, - this->fd, buffer.m.offset); -#endif if (MAP_FAILED == this->video->buffers[i].start) { lprintf("Couldn't mmap buffer %i\n", i); int j; for(j = 0;jvideo->buffers[i].start, this->video->buffers[i].length); -#else - munmap(this->video->buffers[i].start, this->video->buffers[i].length); -#endif } free(this->video->buffers); this->video->bufcount = 0; @@ -200,31 +180,23 @@ int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { } v4l2_input_enqueue_video_buffer(this, i); } - + struct v4l2_format fmt; memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* TODO: Other formats? MPEG support? */ fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; -#ifdef HAVE_LIBV4L2_H v4l2_ioctl(this->fd, VIDIOC_S_FMT, &fmt); -#else - ioctl(this->fd, VIDIOC_S_FMT, &fmt); -#endif this->video->resolution.width = fmt.fmt.pix.width; this->video->resolution.height = fmt.fmt.pix.height; -#ifdef HAVE_LIBV4L2_H if (-1 == v4l2_ioctl(this->fd, VIDIOC_STREAMON, &reqbuf.type)) { -#else - if (-1 == ioctl(this->fd, VIDIOC_STREAMON, &reqbuf.type)) { -#endif lprintf("Couldn't start streaming: %s\n", strerror(errno)); return 0; } return 1; } -buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t len) { +static buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t len) { lprintf("Reading block\n"); v4l2_input_plugin_t *this = (v4l2_input_plugin_t*)this_gen; buf_element_t *buf = fifo->buffer_pool_alloc(fifo); @@ -235,7 +207,7 @@ buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffer_t *fi lprintf("Sending video header\n"); xine_bmiheader bih; bih.biSize = sizeof(xine_bmiheader); - /* HACK: Why do I need to do this and why is it magic? */ + /* HACK: Why do I need to do this and why is it magic? */ bih.biWidth = this->video->resolution.width*2; bih.biHeight = this->video->resolution.height*2; lprintf("Getting size of %ix%i\n", this->video->resolution.width, this->video->resolution.height); @@ -253,94 +225,74 @@ buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffer_t *fi return buf; } -uint32_t v4l2_input_blocksize(input_plugin_t *this_gen) { +static uint32_t v4l2_input_blocksize(input_plugin_t *this_gen) { /* HACK */ return 0; v4l2_input_plugin_t *this = (v4l2_input_plugin_t*)this_gen; if (this->video->headerSent) { - lprintf("Returning block size of %i\n",this->video->buffers[0].length); + lprintf("Returning block size of %zu\n",this->video->buffers[0].length); return this->video->buffers[0].length; } else { - lprintf("Returning block size of %i\n",sizeof(xine_bmiheader)); + lprintf("Returning block size of %zu\n",sizeof(xine_bmiheader)); return sizeof(xine_bmiheader); } } -void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *output) { +static void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *output) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; output->content = output->mem; -#ifdef HAVE_LIBV4L2_H v4l2_ioctl(this->fd, VIDIOC_DQBUF, &buf); -#else - ioctl(this->fd, VIDIOC_DQBUF, &buf); -#endif output->decoder_flags = BUF_FLAG_FRAME_START|BUF_FLAG_FRAME_END; xine_fast_memcpy(output->content, this->video->buffers[buf.index].start, this->video->buffers[buf.index].length); output->type = BUF_VIDEO_YUY2; v4l2_input_enqueue_video_buffer(this, buf.index); } -void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx) { +static void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.index = idx; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; -#ifdef HAVE_LIBV4L2_H v4l2_ioctl(this->fd, VIDIOC_QBUF, &buf); -#else - ioctl(this->fd, VIDIOC_QBUF, &buf); -#endif } -void v4l2_input_dispose(input_plugin_t *this_gen) { +static void v4l2_input_dispose(input_plugin_t *this_gen) { lprintf("Disposing of myself.\n"); v4l2_input_plugin_t* this = (v4l2_input_plugin_t*)this_gen; - + if (this->video != NULL) { int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -#ifdef HAVE_LIBV4L2_H if (-1 == v4l2_ioctl(this->fd, VIDIOC_STREAMOFF, &type)) { -#else - if (-1 == ioctl(this->fd, VIDIOC_STREAMOFF, &type)) { -#endif lprintf("Couldn't stop streaming. Uh oh.\n"); } if (this->video->bufcount > 0) { int i; for(i = 0;ivideo->bufcount;i++) { -#ifdef HAVE_LIBV4L2_H v4l2_munmap(this->video->buffers[i].start, this->video->buffers[i].length); -#else - munmap(this->video->buffers[i].start, this->video->buffers[i].length); -#endif } free(this->video->buffers); } free(this->video); } -#ifdef HAVE_LIBV4L2_H v4l2_close(this->fd); -#else - close(this->fd); -#endif free(this->mrl); free(this); } -off_t v4l2_input_read(input_plugin_t *this_gen, char *buf, off_t nlen) { +static off_t v4l2_input_read(input_plugin_t *this_gen, char *buf, off_t nlen) { /* Only block reads are supported. */ return 0; } -uint32_t v4l2_input_get_capabilities(input_plugin_t* this_gen) { +static uint32_t v4l2_input_get_capabilities(input_plugin_t* this_gen) { return INPUT_CAP_BLOCK; } -const char* v4l2_input_get_mrl(input_plugin_t* this_gen) { +static const char* v4l2_input_get_mrl(input_plugin_t* this_gen) { v4l2_input_plugin_t* this = (v4l2_input_plugin_t*)this_gen; /* HACK HACK HACK HACK */ /* So far, the only way to get the yuv_frames demuxer to work with this */ @@ -348,30 +300,30 @@ const char* v4l2_input_get_mrl(input_plugin_t* this_gen) { //return this->mrl; } -int v4l2_input_get_optional_data(input_plugin_t *this_gen, void *data, int data_type) { +static int v4l2_input_get_optional_data(input_plugin_t *this_gen, void *data, int data_type) { return INPUT_OPTIONAL_UNSUPPORTED; } /* Seeking not supported. */ -off_t v4l2_input_seek(input_plugin_t *this_gen, off_t offset, int origin) { +static off_t v4l2_input_seek(input_plugin_t *this_gen, off_t offset, int origin) { return -1; } -off_t v4l2_input_seek_time(input_plugin_t *this_gen, int time_offset, int origin) { +static off_t v4l2_input_seek_time(input_plugin_t *this_gen, int time_offset, int origin) { return -1; } -off_t v4l2_input_pos(input_plugin_t *this_gen) { +static off_t v4l2_input_pos(input_plugin_t *this_gen) { /* TODO */ return 0; } -int v4l2_input_time(input_plugin_t *this_gen) { +static int v4l2_input_time(input_plugin_t *this_gen) { /* TODO */ return 0; } -off_t v4l2_input_length(input_plugin_t *this_gen) { +static off_t v4l2_input_length(input_plugin_t *this_gen) { return -1; } @@ -443,8 +395,8 @@ const input_info_t input_info_v4l2 = { 4000 }; -const plugin_info_t xine_plugin_info[] = { - /* type, API, "name", version, special_info, init_function */ +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT, 17, "v4l2", XINE_VERSION_CODE, &input_info_v4l2, v4l2_init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; -- cgit v1.2.3 From 4fc7f9d52eb06a1c16a6af76b3d20db2b06a0d8b Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 21 Jan 2010 01:43:19 +0000 Subject: Require v4l2:/ prefix. --HG-- branch : v4l --- src/input/input_v4l2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index 1e6da1e78..295e991eb 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -333,9 +333,14 @@ typedef struct { static input_plugin_t *v4l2_class_get_instance(input_class_t *gen_cls, xine_stream_t *stream, const char *mrl) { v4l2_input_plugin_t *this; + if (strncasecmp (mrl, "v4l2:/", 6)) + return NULL; + mrl += 5; + while (*++mrl == '/') /**/; + --mrl; /* point at the last slash */ /* TODO: Radio devices */ /* FIXME: Don't require devices to be of /dev/videoXXX */ - if (strncmp(mrl, "/dev/video", strlen("/dev/video")) != 0) + if (strncmp(mrl, "/dev/video", 10) != 0) return NULL; lprintf("We can handle %s!\n", mrl); -- cgit v1.2.3 From cc1a46cebce07d4f0d3417b3354fe367fa3c984b Mon Sep 17 00:00:00 2001 From: Trever Fischer Date: Wed, 6 Jan 2010 12:21:25 -0500 Subject: Add v4l2 to the makefile --HG-- branch : v4l --- src/input/Makefile.am | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/input/Makefile.am b/src/input/Makefile.am index 0748c8f29..3c700ea46 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -21,6 +21,7 @@ endif if HAVE_V4L in_v4l = xineplug_inp_v4l.la +in_v4l2 = xineplug_inp_v4l2.la in_pvr = xineplug_inp_pvr.la endif @@ -60,6 +61,7 @@ xineplug_LTLIBRARIES = \ $(in_dvd) \ $(in_vcd) \ $(in_v4l) \ + $(in_v4l2) \ $(in_gnome_vfs) \ $(in_smb) \ xineplug_inp_mms.la \ @@ -138,6 +140,11 @@ xineplug_inp_v4l_la_LIBADD = $(XINE_LIB) $(ALSA_LIBS) $(LTLIBINTL) xineplug_inp_v4l_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) xineplug_inp_v4l_la_LDFLAGS = -avoid-version -module +xineplug_inp_v4l2_la_SOURCES = input_v4l2.c +xineplug_inp_v4l2_la_LIBADD = $(XINE_LIB) $(ALSA_LIBS) +xineplug_inp_v4l2_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) +xineplug_inp_v4l2_la_LDFLAGS = -avoid-version -module + xineplug_inp_gnome_vfs_la_SOURCES = input_gnome_vfs.c net_buf_ctrl.c xineplug_inp_gnome_vfs_la_LIBADD = $(XINE_LIB) $(GNOME_VFS_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_inp_gnome_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) -- cgit v1.2.3 From 76d6a14f1d72ac8afd3398d268cd1b91752331be Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 21 Jan 2010 16:29:50 +0000 Subject: Backport YUV build optimisation. --- src/video_out/Makefile.am | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 3e182fc14..84712db66 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -86,6 +86,14 @@ if HAVE_MACOSX_VIDEO macosx_module = xineplug_vo_out_macosx.la endif +noinst_LTLIBRARIES = libyuv2rgb.la + +libyuv2rgb_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c +libyuv2rgb_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) + +# All YUV lib info here to avoid polluting the .la with this info +YUV_LIBS = libyuv2rgb.la $(XINE_LIB) $(MLIB_LIBS) + xineplug_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \ $(opengl_module) \ $(syncfb_module) \ @@ -104,17 +112,16 @@ xineplug_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \ xineplug_vo_out_raw.la \ xineplug_vo_out_none.la -xineplug_vo_out_xcbshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_xcbshm.c $(XCBOSD) -xineplug_vo_out_xcbshm_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(PTHREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS) $(LTLIBINTL) +xineplug_vo_out_xcbshm_la_SOURCES = video_out_xcbshm.c $(XCBOSD) +xineplug_vo_out_xcbshm_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS) $(LTLIBINTL) xineplug_vo_out_xcbshm_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS) xineplug_vo_out_xcbxv_la_SOURCES = deinterlace.c video_out_xcbxv.c $(XCBOSD) xineplug_vo_out_xcbxv_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) $(XCBXV_LIBS) $(XCB_LIBS) xineplug_vo_out_xcbxv_la_CFLAGS = $(VISIBILITY_FLAG) $(XCB_CFLAGS) $(XCBXV_CFLAGS) -xineplug_vo_out_xshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \ - video_out_xshm.c $(X11OSD) -xineplug_vo_out_xshm_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_vo_out_xshm_la_SOURCES = video_out_xshm.c $(X11OSD) +xineplug_vo_out_xshm_la_LIBADD = $(YUV_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_xshm_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(MLIB_CFLAGS) -fno-strict-aliasing xineplug_vo_out_xv_la_SOURCES = $(X11OSD) deinterlace.c video_out_xv.c @@ -130,9 +137,8 @@ xineplug_vo_out_xxmc_la_SOURCES = $(X11OSD) deinterlace.c video_out_xxmc.c\ xineplug_vo_out_xxmc_la_LIBADD = $(XINE_LIB) $(XXMC_LIBS) $(XV_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_xxmc_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(XV_CFLAGS) -fno-strict-aliasing -xineplug_vo_out_opengl_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \ - video_out_opengl.c myglext.h $(X11OSD) -xineplug_vo_out_opengl_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(OPENGL_LIBS) \ +xineplug_vo_out_opengl_la_SOURCES = video_out_opengl.c myglext.h $(X11OSD) +xineplug_vo_out_opengl_la_LIBADD = $(YUV_LIBS) $(OPENGL_LIBS) \ $(GLUT_LIBS) $(GLU_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) xineplug_vo_out_opengl_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(MLIB_CFLAGS) -fno-strict-aliasing @@ -157,14 +163,12 @@ xineplug_vo_out_aa_la_SOURCES = video_out_aa.c xineplug_vo_out_aa_la_LIBADD = $(XINE_LIB) $(AALIB_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_aa_la_CFLAGS = $(VISIBILITY_FLAG) $(AALIB_CFLAGS) -xineplug_vo_out_caca_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \ - video_out_caca.c -xineplug_vo_out_caca_la_LIBADD = $(XINE_LIB) $(CACA_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_vo_out_caca_la_SOURCES = video_out_caca.c +xineplug_vo_out_caca_la_LIBADD = $(YUV_LIBS) $(CACA_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_caca_la_CFLAGS = $(VISIBILITY_FLAG) $(CACA_CFLAGS) -xineplug_vo_out_fb_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \ - video_out_fb.c -xineplug_vo_out_fb_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_vo_out_fb_la_SOURCES = video_out_fb.c +xineplug_vo_out_fb_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_fb_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) xineplug_vo_out_directfb_la_SOURCES = video_out_directfb_fb.c @@ -183,17 +187,17 @@ xineplug_vo_out_stk_la_SOURCES = video_out_stk.c xineplug_vo_out_stk_la_LIBADD = $(XINE_LIB) $(LIBSTK_LIBS) $(PTHREAD_LIBS) xineplug_vo_out_stk_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBSTK_CFLAGS) -xineplug_vo_out_directx_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c video_out_directx.c +xineplug_vo_out_directx_la_SOURCES = video_out_directx.c xineplug_vo_out_directx_la_CPPFLAGS = $(AM_CPPFLAGS) $(DIRECTX_CPPFLAGS) -xineplug_vo_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_vo_out_directx_la_LIBADD = $(YUV_LIBS) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_directx_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_vo_out_none_la_SOURCES = video_out_none.c xineplug_vo_out_none_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_none_la_CFLAGS = $(VISIBILITY_FLAG) -xineplug_vo_out_raw_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_raw.c -xineplug_vo_out_raw_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_vo_out_raw_la_SOURCES = video_out_raw.c +xineplug_vo_out_raw_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_raw_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_vo_out_macosx_la_SOURCES = video_out_macosx.m -- cgit v1.2.3 From 50fa703235d9478efb37374ccf9d009e875cd2d1 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 21 Jan 2010 22:01:35 +0000 Subject: Revert a038e9625e79 (breaks A/V sync). --- src/demuxers/demux_ts.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 1a016fea9..1a19340f3 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -987,7 +987,6 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, m->buf->decoder_flags |= BUF_FLAG_FRAME_END; } m->buf->pts = m->pts; - m->pts = 0; m->buf->decoder_info[0] = 1; if( this->input->get_length (this->input) ) @@ -996,12 +995,12 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, if (this->rate) m->buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) * 1000 / (this->rate * 50)); -#ifdef TS_LOG - printf ("demux_ts: produced buffer, pts=%lld\n", m->buf->pts); -#endif m->fifo->put(m->fifo, m->buf); m->buffered_bytes = 0; m->buf = NULL; /* forget about buf -- not our responsibility anymore */ +#ifdef TS_LOG + printf ("demux_ts: produced buffer, pts=%lld\n", m->pts); +#endif } /* allocate the buffer here, as pes_header needs a valid buf for dvbsubs */ m->buf = m->fifo->buffer_pool_alloc(m->fifo); @@ -1034,7 +1033,6 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, m->buf->size = m->buffered_bytes; m->buf->type = m->type; m->buf->pts = m->pts; - m->pts = 0; m->buf->decoder_info[0] = 1; if( this->input->get_length (this->input) ) m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * @@ -1042,12 +1040,15 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, if (this->rate) m->buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) * 1000 / (this->rate * 50)); -#ifdef TS_LOG - printf ("demux_ts: produced buffer, pts=%lld\n", m->buf->pts); -#endif + m->fifo->put(m->fifo, m->buf); m->buffered_bytes = 0; m->buf = m->fifo->buffer_pool_alloc(m->fifo); + +#ifdef TS_LOG + printf ("demux_ts: produced buffer, pts=%lld\n", m->pts); +#endif + } memcpy(m->buf->mem + m->buffered_bytes, ts, len); m->buffered_bytes += len; -- cgit v1.2.3 From 83bdb6a494f25c8e812fa84611076d8a60eabd01 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 22 Jan 2010 00:46:53 +0000 Subject: v4l2: set stream audio/video flags; check for VIDIOC_S_FMT failure. --HG-- branch : v4l --- src/input/input_v4l2.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index 295e991eb..43b28b8d5 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -186,16 +186,24 @@ static int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* TODO: Other formats? MPEG support? */ fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - v4l2_ioctl(this->fd, VIDIOC_S_FMT, &fmt); + if (-1 == v4l2_ioctl(this->fd, VIDIOC_S_FMT, &fmt)) + goto fail; this->video->resolution.width = fmt.fmt.pix.width; this->video->resolution.height = fmt.fmt.pix.height; - if (-1 == v4l2_ioctl(this->fd, VIDIOC_STREAMON, &reqbuf.type)) { - lprintf("Couldn't start streaming: %s\n", strerror(errno)); - return 0; - } + if (-1 == v4l2_ioctl(this->fd, VIDIOC_STREAMON, &reqbuf.type)) + goto fail; + + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); + return 1; + + fail: + lprintf("Couldn't start streaming: %s\n", strerror(errno)); + return 0; } + static buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t len) { lprintf("Reading block\n"); v4l2_input_plugin_t *this = (v4l2_input_plugin_t*)this_gen; -- cgit v1.2.3 From c6e375017d56bf660c337f750b0ee04df69afbbf Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 22 Jan 2010 01:03:27 +0000 Subject: v4l2: set no. of bytes sent, and don't send more than max_size bytes at a time. --HG-- branch : v4l --- src/input/input_v4l2.c | 55 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index 43b28b8d5..69d0a3b75 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -68,6 +68,8 @@ typedef struct { buffer_data *buffers; int bufcount; resolution_t resolution; + struct v4l2_buffer inbuf; + off_t index; int headerSent; } v4l2_video_t; @@ -90,7 +92,7 @@ typedef struct { } v4l2_input_plugin_t; static void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx); -static void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *input); +static int v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *input); static int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this); @@ -208,10 +210,11 @@ static buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffe lprintf("Reading block\n"); v4l2_input_plugin_t *this = (v4l2_input_plugin_t*)this_gen; buf_element_t *buf = fifo->buffer_pool_alloc(fifo); - struct timeval tv; - xine_monotonic_clock(&tv, NULL); - buf->pts = (int64_t) tv.tv_sec * 90000 + (int64_t) tv.tv_usec * 9 / 100; if (!this->video->headerSent) { + struct timeval tv; + xine_monotonic_clock(&tv, NULL); + buf->pts = (int64_t) tv.tv_sec * 90000 + (int64_t) tv.tv_usec * 9 / 100; + lprintf("Sending video header\n"); xine_bmiheader bih; bih.biSize = sizeof(xine_bmiheader); @@ -223,12 +226,12 @@ static buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffe buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_START; memcpy(buf->content, &bih, sizeof(xine_bmiheader)); this->video->headerSent = 1; + this->video->index = 0; buf->type = BUF_VIDEO_YUY2; } else { - lprintf("Sending video frame\n"); + lprintf("Sending video frame (sent %d of %d)\n", this->video->index, this->video->buffers[this->video->inbuf.index].length); /* TODO: Add audio support */ - v4l2_input_dequeue_video_buffer(this, buf); - this->video->headerSent = 0; + this->video->headerSent = v4l2_input_dequeue_video_buffer(this, buf); } return buf; } @@ -246,17 +249,37 @@ static uint32_t v4l2_input_blocksize(input_plugin_t *this_gen) { } } -static void v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *output) { - struct v4l2_buffer buf; - memset(&buf, 0, sizeof(buf)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; +static int v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *output) +{ + if (!this->video->index) + { + memset (&this->video->inbuf, 0, sizeof (this->video->inbuf)); + this->video->inbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + this->video->inbuf.memory = V4L2_MEMORY_MMAP; + v4l2_ioctl(this->fd, VIDIOC_DQBUF, &this->video->inbuf); + output->decoder_flags = BUF_FLAG_FRAME_START; + } + else + output->decoder_flags = 0; + output->content = output->mem; - v4l2_ioctl(this->fd, VIDIOC_DQBUF, &buf); - output->decoder_flags = BUF_FLAG_FRAME_START|BUF_FLAG_FRAME_END; - xine_fast_memcpy(output->content, this->video->buffers[buf.index].start, this->video->buffers[buf.index].length); output->type = BUF_VIDEO_YUY2; - v4l2_input_enqueue_video_buffer(this, buf.index); + + output->size = this->video->buffers[this->video->inbuf.index].length - this->video->index; + if (output->size > output->max_size) + output->size = output->max_size; + + xine_fast_memcpy (output->content, this->video->buffers[this->video->inbuf.index].start + this->video->index, output->size); + + this->video->index += output->size; + if (this->video->index == this->video->buffers[this->video->inbuf.index].length) + { + output->decoder_flags |= BUF_FLAG_FRAME_END; + v4l2_input_enqueue_video_buffer(this, this->video->inbuf.index); + return 0; + } + + return 1; } static void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx) { -- cgit v1.2.3 From 16cd864eb5fec7e7462dd446a5ddd7e9ffcfacd2 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 26 Jan 2010 01:25:32 +0000 Subject: Fix AAC in FLV. This bug appears to be a variety of aliasing bug, caused by the compiler not knowing that buffer is written to by ...->read(). On i386, the bug shows up because buffer[0] has to be re-read when extracting the sample rate etc.; on amd64, it works fine because the value was cached in a register. The problem is avoided by not read()ing into any storage more than once while it remains in scope. --- src/demuxers/demux_flv.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/demuxers/demux_flv.c b/src/demuxers/demux_flv.c index 813f33086..6b5a72a1b 100644 --- a/src/demuxers/demux_flv.c +++ b/src/demuxers/demux_flv.c @@ -395,14 +395,15 @@ static void parse_flv_script(demux_flv_t *this, int size) { static int read_flv_packet(demux_flv_t *this, int preview) { fifo_buffer_t *fifo = NULL; buf_element_t *buf = NULL; - unsigned char buffer[12]; - unsigned char tag_type; - unsigned int remaining_bytes; - unsigned int buf_type = 0; - unsigned int buf_flags = 0; - unsigned int pts; while (1) { + unsigned char buffer[12], extrabuffer[4]; + unsigned char tag_type, avinfo; + unsigned int remaining_bytes; + unsigned int buf_type = 0; + unsigned int buf_flags = 0; + unsigned int pts; + lprintf (" reading FLV tag...\n"); this->input->seek(this->input, 4, SEEK_CUR); if (this->input->read(this->input, buffer, 11) != 11) { @@ -420,13 +421,13 @@ static int read_flv_packet(demux_flv_t *this, int preview) { switch (tag_type) { case FLV_TAG_TYPE_AUDIO: lprintf(" got audio tag..\n"); - if (this->input->read(this->input, buffer, 1) != 1) { + if (this->input->read(this->input, &avinfo, 1) != 1) { this->status = DEMUX_FINISHED; return this->status; } remaining_bytes--; - this->audiocodec = buffer[0] >> 4; /* override */ + this->audiocodec = avinfo >> 4; /* override */ switch (this->audiocodec) { case FLV_SOUND_FORMAT_PCM_BE: buf_type = BUF_AUDIO_LPCM_BE; @@ -450,11 +451,11 @@ static int read_flv_packet(demux_flv_t *this, int preview) { case FLV_SOUND_FORMAT_AAC: buf_type = BUF_AUDIO_AAC; /* AAC extra header */ - this->input->read(this->input, buffer, 1 ); + this->input->read(this->input, extrabuffer, 1 ); remaining_bytes--; break; default: - lprintf(" unsupported audio format (%d)...\n", buffer[0] >> 4); + lprintf(" unsupported audio format (%d)...\n", this->audiocodec); buf_type = BUF_AUDIO_UNKNOWN; break; } @@ -465,9 +466,9 @@ static int read_flv_packet(demux_flv_t *this, int preview) { buf = fifo->buffer_pool_alloc(fifo); buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_STDHEADER | BUF_FLAG_FRAME_END; buf->decoder_info[0] = 0; - buf->decoder_info[1] = 44100 >> (3 - ((buffer[0] >> 2) & 3)); /* samplerate */ - buf->decoder_info[2] = (buffer[0] & 2) ? 16 : 8; /* bits per sample */ - buf->decoder_info[3] = (buffer[0] & 1) + 1; /* channels */ + buf->decoder_info[1] = 44100 >> (3 - ((avinfo >> 2) & 3)); /* samplerate */ + buf->decoder_info[2] = (avinfo & 2) ? 16 : 8; /* bits per sample */ + buf->decoder_info[3] = (avinfo & 1) + 1; /* channels */ buf->size = 0; /* no extra data */ buf->type = buf_type; fifo->put(fifo, buf); @@ -477,13 +478,13 @@ static int read_flv_packet(demux_flv_t *this, int preview) { case FLV_TAG_TYPE_VIDEO: lprintf(" got video tag..\n"); - if (this->input->read(this->input, buffer, 1) != 1) { + if (this->input->read(this->input, &avinfo, 1) != 1) { this->status = DEMUX_FINISHED; return this->status; } remaining_bytes--; - switch ((buffer[0] >> 4)) { + switch ((avinfo >> 4)) { case 0x01: buf_flags = BUF_FLAG_KEYFRAME; break; @@ -495,7 +496,7 @@ static int read_flv_packet(demux_flv_t *this, int preview) { break; } - this->videocodec = buffer[0] & 0x0F; /* override */ + this->videocodec = avinfo & 0x0F; /* override */ switch (this->videocodec) { case FLV_VIDEO_FORMAT_FLV1: buf_type = BUF_VIDEO_FLV1; @@ -503,23 +504,23 @@ static int read_flv_packet(demux_flv_t *this, int preview) { case FLV_VIDEO_FORMAT_VP6: buf_type = BUF_VIDEO_VP6F; /* VP6 extra header */ - this->input->read(this->input, buffer, 1 ); + this->input->read(this->input, extrabuffer, 1 ); remaining_bytes--; break; case FLV_VIDEO_FORMAT_VP6A: buf_type = BUF_VIDEO_VP6F; /* VP6A extra header */ - this->input->read(this->input, buffer, 4); + this->input->read(this->input, extrabuffer, 4); remaining_bytes -= 4; break; case FLV_VIDEO_FORMAT_H264: buf_type = BUF_VIDEO_H264; /* AVC extra header */ - this->input->read(this->input, buffer, 4); + this->input->read(this->input, extrabuffer, 4); remaining_bytes -= 4; break; default: - lprintf(" unsupported video format (%d)...\n", buffer[0] & 0x0F); + lprintf(" unsupported video format (%d)...\n", this->videocodec); buf_type = BUF_VIDEO_UNKNOWN; break; } @@ -541,11 +542,11 @@ static int read_flv_packet(demux_flv_t *this, int preview) { buf->size = sizeof(xine_bmiheader); buf->type = buf_type; if (buf_type == BUF_VIDEO_VP6F) { - *((unsigned char *)buf->content+buf->size) = buffer[0]; + *((unsigned char *)buf->content+buf->size) = extrabuffer[0]; bih->biSize++; buf->size++; } - else if (buf_type == BUF_VIDEO_H264 && buffer[0] == 0) { + else if (buf_type == BUF_VIDEO_H264 && extrabuffer[0] == 0) { /* AVC sequence header */ if (remaining_bytes > buf->max_size-buf->size) { xprintf(this->xine, XINE_VERBOSITY_LOG, @@ -670,7 +671,7 @@ static int read_flv_packet(demux_flv_t *this, int preview) { (int)((double)this->input->get_current_pos(this->input) * 65535.0 / this->size); } - if ((buf_type == BUF_VIDEO_H264 || buf_type == BUF_AUDIO_AAC) && buffer[0] == 0) { + if ((buf_type == BUF_VIDEO_H264 || buf_type == BUF_AUDIO_AAC) && extrabuffer[0] == 0) { /* AVC/AAC sequence header */ buf->pts = 0; buf->size = 0; -- cgit v1.2.3