aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Krasnyansky <maxk@qualcomm.com>2003-01-22 22:40:52 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-01-22 22:40:52 +0000
commit8aa3ee32c257541a91bab1e47364f4f655e9e69d (patch)
tree2f3593864ea116c97fd180f40e5ac3244d8e3b13
parent4b8b2edb6260d0f0b9e5f2f10a28c3ab19143f2f (diff)
downloadffmpeg-8aa3ee32c257541a91bab1e47364f4f655e9e69d.tar.gz
dv patch by Max Krasnyansky (maxk at qualcomm dot com)
Originally committed as revision 1493 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rwxr-xr-xconfigure19
-rw-r--r--ffmpeg.c21
-rw-r--r--libavformat/Makefile4
-rw-r--r--libavformat/allformats.c6
-rw-r--r--libavformat/dv1394.c249
-rw-r--r--libavformat/dv1394.h353
-rw-r--r--libavformat/grab.c8
7 files changed, 648 insertions, 12 deletions
diff --git a/configure b/configure
index 59f5b798b2..b0834dfaac 100755
--- a/configure
+++ b/configure
@@ -53,6 +53,7 @@ gprof="no"
v4l="yes"
audio_oss="yes"
audio_beos="no"
+dv1394="yes"
network="yes"
zlib="yes"
mp3lame="no"
@@ -103,6 +104,7 @@ SHFLAGS=-nostart
# disable linux things
audio_oss="no"
v4l="no"
+dv1394="no"
# enable beos things
audio_beos="yes"
# no need for libm, but the inet stuff
@@ -117,6 +119,7 @@ fi ;;
SunOS)
v4l="no"
audio_oss="no"
+dv1394="no"
make="gmake"
LDFLAGS=""
FFSLDFLAGS=""
@@ -126,12 +129,14 @@ extralibs="$extralibs -lsocket -lnsl"
FreeBSD)
v4l="no"
audio_oss="yes"
+dv1394="no"
make="gmake"
LDFLAGS="$LDFLAGS -export-dynamic"
;;
BSD/OS)
v4l="no"
audio_oss="yes"
+dv1394="no"
extralibs="-lpoll -lgnugetopt -lm"
make="gmake"
;;
@@ -139,6 +144,7 @@ Darwin)
cc="cc"
v4l="no"
audio_oss="no"
+dv1394="no"
SHFLAGS="-dynamiclib"
extralibs=""
darwin="yes"
@@ -158,6 +164,7 @@ esac
MINGW32*)
v4l="no"
audio_oss="no"
+dv1394="no"
ffserver="no"
network="no"
mingw32="yes"
@@ -165,6 +172,7 @@ mingw32="yes"
CYGWIN*)
v4l="no"
audio_oss="yes"
+dv1394="no"
extralibs=""
cygwin="yes"
test -f /usr/include/inttypes.h || \
@@ -190,6 +198,7 @@ SLIBSUF=".dll"
extralibs=""
v4l="no"
audio_oss="no"
+dv1394="no"
network="no"
ffserver="no"
os2="yes"
@@ -287,6 +296,8 @@ for opt do
;;
--disable-audio-beos) audio_beos="no"
;;
+ --disable-dv1394) dv1394="no"
+ ;;
--disable-network) network="no"
;;
--disable-zlib) zlib="no"
@@ -375,6 +386,7 @@ if test "$win32" = "yes" ; then
cross_prefix="i386-mingw32msvc-"
v4l="no"
audio_oss="no"
+ dv1394="no"
network="no"
fi
@@ -382,6 +394,7 @@ if test "$mingw32" = "yes" ; then
cross_prefix=""
v4l="no"
audio_oss="no"
+ dv1394="no"
network="no"
fi
@@ -543,6 +556,7 @@ echo " --disable-altivec disable AltiVec usage"
echo " --disable-audio-oss disable OSS audio support [default=no]"
echo " --disable-audio-beos disable BeOS audio support [default=no]"
echo " --disable-v4l disable video4linux grabbing [default=no]"
+echo " --disable-dv1394 disable DV1394 grabbing [default=no]"
echo " --disable-network disable network support [default=no]"
echo " --disable-zlib disable zlib [default=no]"
echo " --disable-simple_idct disable simple IDCT routines [default=no]"
@@ -705,6 +719,11 @@ if test "$v4l" = "yes" ; then
echo "CONFIG_VIDEO4LINUX=yes" >> config.mak
fi
+if test "$dv1394" = "yes" ; then
+ echo "#define CONFIG_DV1394 1" >> $TMPH
+ echo "CONFIG_DV1394=yes" >> config.mak
+fi
+
if test "$dlopen" = "yes" ; then
echo "#define CONFIG_HAVE_DLOPEN 1" >> $TMPH
fi
diff --git a/ffmpeg.c b/ffmpeg.c
index 4f4a5f3831..1e1b4b0d92 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -158,14 +158,14 @@ static char *pass_logfilename = NULL;
static int audio_stream_copy = 0;
static int video_stream_copy = 0;
+static char *video_grab_format = "video4linux";
+static char *audio_grab_format = "audio_device";
+
#define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass"
#if !defined(CONFIG_AUDIO_OSS) && !defined(CONFIG_AUDIO_BEOS)
const char *audio_device = "none";
#endif
-#ifndef CONFIG_VIDEO4LINUX
-const char *v4l_device = "none";
-#endif
typedef struct AVOutputStream {
int file_index; /* file index */
@@ -1870,7 +1870,7 @@ void opt_audio_channels(const char *arg)
void opt_video_device(const char *arg)
{
- v4l_device = strdup(arg);
+ video_device = strdup(arg);
}
void opt_audio_device(const char *arg)
@@ -1878,6 +1878,12 @@ void opt_audio_device(const char *arg)
audio_device = strdup(arg);
}
+void opt_dv1394(const char *arg)
+{
+ video_grab_format = "dv1394";
+ audio_grab_format = "none";
+}
+
void opt_audio_codec(const char *arg)
{
AVCodec *p;
@@ -2455,7 +2461,7 @@ void prepare_grab(void)
if (has_video) {
AVInputFormat *fmt1;
- fmt1 = av_find_input_format("video_grab_device");
+ fmt1 = av_find_input_format(video_grab_format);
if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) {
fprintf(stderr, "Could not find video grab device\n");
exit(1);
@@ -2463,12 +2469,12 @@ void prepare_grab(void)
/* by now video grab has one stream */
ic->streams[0]->r_frame_rate = ap->frame_rate;
input_files[nb_input_files] = ic;
- dump_format(ic, nb_input_files, v4l_device, 0);
+ dump_format(ic, nb_input_files, video_device, 0);
nb_input_files++;
}
if (has_audio) {
AVInputFormat *fmt1;
- fmt1 = av_find_input_format("audio_device");
+ fmt1 = av_find_input_format(audio_grab_format);
if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) {
fprintf(stderr, "Could not find audio grab device\n");
exit(1);
@@ -2692,6 +2698,7 @@ const OptionDef options[] = {
{ "minrate", HAS_ARG, {(void*)opt_video_bitrate_min}, "set min video bitrate tolerance (in kbit/s)", "bitrate" },
{ "bufsize", HAS_ARG, {(void*)opt_video_buffer_size}, "set ratecontrol buffere size (in kbit)", "size" },
{ "vd", HAS_ARG | OPT_EXPERT, {(void*)opt_video_device}, "set video grab device", "device" },
+ { "dv1394", OPT_EXPERT, {(void*)opt_dv1394}, "set DV1394 options", "[channel]" },
{ "vcodec", HAS_ARG | OPT_EXPERT, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" },
{ "me", HAS_ARG | OPT_EXPERT, {(void*)opt_motion_estimation}, "set motion estimation method",
"method" },
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 897c4014dd..e3fcbd7179 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -28,6 +28,10 @@ ifeq ($(CONFIG_VIDEO4LINUX),yes)
OBJS+= grab.o
endif
+ifeq ($(CONFIG_DV1394),yes)
+OBJS+= dv1394.o
+endif
+
ifeq ($(CONFIG_AUDIO_OSS),yes)
OBJS+= audio.o
endif
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 98702e4795..8e8c9f059f 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -21,6 +21,8 @@
/* If you do not call this function, then you can select exactly which
formats you want to support */
+char *video_device = "none";
+
/**
* Initialize libavcodec and register all the codecs and formats.
*/
@@ -62,6 +64,10 @@ void av_register_all(void)
audio_init();
#endif
+#ifdef CONFIG_DV1394
+ dv1394_init();
+#endif
+
/* image formats */
av_register_image_format(&pnm_image_format);
av_register_image_format(&pbm_image_format);
diff --git a/libavformat/dv1394.c b/libavformat/dv1394.c
new file mode 100644
index 0000000000..8515160545
--- /dev/null
+++ b/libavformat/dv1394.c
@@ -0,0 +1,249 @@
+/*
+ * Linux DV1394 interface
+ * Copyright (c) 2003 Max Krasnyansky <maxk@qualcomm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "avformat.h"
+
+#undef DV1394_DEBUG
+
+#include "dv1394.h"
+
+int dv1394_channel = DV1394_DEFAULT_CHANNEL;
+
+struct dv1394_data {
+ int fd;
+ int channel;
+ int width, height;
+ int frame_rate;
+ int frame_size;
+
+ void *ring; /* Ring buffer */
+ int index; /* Current frame index */
+ int avail; /* Number of frames available for reading */
+ int done; /* Number of completed frames */
+};
+
+static int dv1394_reset(struct dv1394_data *dv)
+{
+ struct dv1394_init init;
+
+ init.channel = dv->channel;
+ init.api_version = DV1394_API_VERSION;
+ init.n_frames = DV1394_RING_FRAMES;
+ init.format = DV1394_NTSC;
+
+ if (ioctl(dv->fd, DV1394_INIT, &init) < 0)
+ return -1;
+
+ dv->avail = 0;
+ return 0;
+}
+
+static int dv1394_start(struct dv1394_data *dv)
+{
+ /* Tell DV1394 driver to enable receiver */
+ if (ioctl(dv->fd, DV1394_START_RECEIVE, 0) < 0) {
+ perror("Failed to start receiver");
+ return -1;
+ }
+ return 0;
+}
+
+static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap)
+{
+ struct dv1394_data *dv = context->priv_data;
+ AVStream *st;
+
+ st = av_new_stream(context, 0);
+ if (!st)
+ return -ENOMEM;
+
+ dv->width = DV1394_WIDTH;
+ dv->height = DV1394_HEIGHT;
+ dv->channel = dv1394_channel;
+
+ dv->frame_rate = 30;
+
+ dv->frame_size = DV1394_NTSC_FRAME_SIZE;
+
+ /* Open and initialize DV1394 device */
+
+ dv->fd = open(video_device, O_RDONLY);
+ if (dv->fd < 0) {
+ perror("Failed to open DV interface");
+ goto failed;
+ }
+
+ if (dv1394_reset(dv) < 0) {
+ perror("Failed to initialize DV interface");
+ goto failed;
+ }
+
+ dv->ring = mmap(NULL, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES,
+ PROT_READ, MAP_PRIVATE, dv->fd, 0);
+ if (!dv->ring) {
+ perror("Failed to mmap DV ring buffer");
+ goto failed;
+ }
+
+ st->codec.codec_type = CODEC_TYPE_VIDEO;
+ st->codec.codec_id = CODEC_ID_DVVIDEO;
+ st->codec.width = dv->width;
+ st->codec.height = dv->height;
+ st->codec.frame_rate = dv->frame_rate * FRAME_RATE_BASE;
+
+ st->codec.bit_rate = 25000000; /* Consumer DV is 25Mbps */
+
+ av_set_pts_info(context, 48, 1, 1000000);
+
+ if (dv1394_start(dv) < 0)
+ goto failed;
+
+ return 0;
+
+failed:
+ close(dv->fd);
+ av_free(st);
+ return -EIO;
+}
+
+static inline int __copy_frame(struct dv1394_data *dv, void *buf)
+{
+ char *ptr = dv->ring + (dv->index * dv->frame_size);
+
+ memcpy(buf, ptr, dv->frame_size);
+
+ dv->index = (dv->index + 1) % DV1394_RING_FRAMES;
+ dv->avail--;
+ dv->done++;
+
+ return dv->frame_size;
+}
+
+static int dv1394_read_packet(AVFormatContext * context, AVPacket * pkt)
+{
+ struct dv1394_data *dv = context->priv_data;
+ int len;
+
+ if (!dv->avail) {
+ struct dv1394_status s;
+ struct pollfd p;
+ p.fd = dv->fd;
+ p.events = POLLIN | POLLERR | POLLHUP;
+
+ /* Wait until more frames are available */
+ if (poll(&p, 1, -1) < 0) {
+ perror("Poll failed");
+ return -EIO;
+ }
+
+ if (ioctl(dv->fd, DV1394_GET_STATUS, &s) < 0) {
+ perror("Failed to get status");
+ return -EIO;
+ }
+#ifdef DV1394_DEBUG
+ fprintf(stderr, "DV1394: status\n"
+ "\tactive_frame\t%d\n"
+ "\tfirst_clear_frame\t%d\n"
+ "\tn_clear_frames\t%d\n"
+ "\tdropped_frames\t%d\n",
+ s.active_frame, s.first_clear_frame,
+ s.n_clear_frames, s.dropped_frames);
+#endif
+
+ dv->avail = s.n_clear_frames;
+ dv->index = s.first_clear_frame;
+ dv->done = 0;
+
+ if (s.dropped_frames) {
+ fprintf(stderr, "DV1394: Frame drop detected (%d). Reseting ..\n",
+ s.dropped_frames);
+
+ dv1394_reset(dv);
+ dv1394_start(dv);
+ }
+ }
+
+ if (av_new_packet(pkt, dv->frame_size) < 0)
+ return -EIO;
+
+#ifdef DV1394_DEBUG
+ fprintf(stderr, "index %d, avail %d, done %d\n", dv->index, dv->avail,
+ dv->done);
+#endif
+
+ len = __copy_frame(dv, pkt->data);
+ pkt->pts = av_gettime() & ((1LL << 48) - 1);
+
+ if (!dv->avail && dv->done) {
+ /* Request more frames */
+ if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) {
+ /* This usually means that ring buffer overflowed.
+ * We have to reset :(.
+ */
+
+ fprintf(stderr, "DV1394: Ring buffer overflow. Reseting ..\n");
+
+ dv1394_reset(dv);
+ dv1394_start(dv);
+ }
+ }
+
+ return len;
+}
+
+static int dv1394_close(AVFormatContext * context)
+{
+ struct dv1394_data *dv = context->priv_data;
+
+ /* Shutdown DV1394 receiver */
+ if (ioctl(dv->fd, DV1394_SHUTDOWN, 0) < 0)
+ perror("Failed to shutdown DV1394");
+
+ /* Unmap ring buffer */
+ if (munmap(dv->ring, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES) < 0)
+ perror("Failed to munmap DV1394 ring buffer");
+
+ close(dv->fd);
+
+ return 0;
+}
+
+static AVInputFormat dv1394_format = {
+ .name = "dv1394",
+ .long_name = "dv1394 A/V grab",
+ .priv_data_size = sizeof(struct dv1394_data),
+ .read_header = dv1394_read_header,
+ .read_packet = dv1394_read_packet,
+ .read_close = dv1394_close,
+ .flags = AVFMT_NOFILE
+};
+
+int dv1394_init(void)
+{
+ av_register_input_format(&dv1394_format);
+ return 0;
+}
diff --git a/libavformat/dv1394.h b/libavformat/dv1394.h
new file mode 100644
index 0000000000..214c8055df
--- /dev/null
+++ b/libavformat/dv1394.h
@@ -0,0 +1,353 @@
+/*
+ * dv1394.h - DV input/output over IEEE 1394 on OHCI chips
+ * Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
+ * receive, proc_fs by Dan Dennedy <dan@dennedy.org>
+ *
+ * based on:
+ * video1394.h - driver for OHCI 1394 boards
+ * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
+ * Peter Schlaile <udbz@rz.uni-karlsruhe.de>
+ *
+ * This program 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.
+ *
+ * This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DV_1394_H
+#define _DV_1394_H
+
+#define DV1394_DEFAULT_CHANNEL 0x63
+#define DV1394_DEFAULT_CARD 0
+#define DV1394_RING_FRAMES 20
+
+#define DV1394_WIDTH 720
+#define DV1394_HEIGHT 480
+
+/* This is the public user-space interface. Try not to break it. */
+
+#define DV1394_API_VERSION 0x20011127
+
+/* ********************
+ ** **
+ ** DV1394 API **
+ ** **
+ ********************
+
+ There are two methods of operating the DV1394 DV output device.
+
+ 1)
+
+ The simplest is an interface based on write(): simply write
+ full DV frames of data to the device, and they will be transmitted
+ as quickly as possible. The FD may be set for non-blocking I/O,
+ in which case you can use select() or poll() to wait for output
+ buffer space.
+
+ To set the DV output parameters (e.g. whether you want NTSC or PAL
+ video), use the DV1394_INIT ioctl, passing in the parameters you
+ want in a struct dv1394_init.
+
+ Example 1:
+ To play a raw .DV file: cat foo.DV > /dev/dv1394
+ (cat will use write() internally)
+
+ Example 2:
+ static struct dv1394_init init = {
+ 0x63, (broadcast channel)
+ 4, (four-frame ringbuffer)
+ DV1394_NTSC, (send NTSC video)
+ 0, 0 (default empty packet rate)
+ }
+
+ ioctl(fd, DV1394_INIT, &init);
+
+ while(1) {
+ read( <a raw DV file>, buf, DV1394_NTSC_FRAME_SIZE );
+ write( <the dv1394 FD>, buf, DV1394_NTSC_FRAME_SIZE );
+ }
+
+ 2)
+
+ For more control over buffering, and to avoid unnecessary copies
+ of the DV data, you can use the more sophisticated the mmap() interface.
+ First, call the DV1394_INIT ioctl to specify your parameters,
+ including the number of frames in the ringbuffer. Then, calling mmap()
+ on the dv1394 device will give you direct access to the ringbuffer
+ from which the DV card reads your frame data.
+
+ The ringbuffer is simply one large, contiguous region of memory
+ containing two or more frames of packed DV data. Each frame of DV data
+ is 120000 bytes (NTSC) or 144000 bytes (PAL).
+
+ Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES
+ ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl
+ or select()/poll() to wait until the frames are transmitted. Next, you'll
+ need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer
+ frames are clear (ready to be filled with new DV data). Finally, use
+ DV1394_SUBMIT_FRAMES again to send the new data to the DV output.
+
+
+ Example: here is what a four-frame ringbuffer might look like
+ during DV transmission:
+
+
+ frame 0 frame 1 frame 2 frame 3
+
+ *--------------------------------------*
+ | CLEAR | DV data | DV data | CLEAR |
+ *--------------------------------------*
+ <ACTIVE>
+
+ transmission goes in this direction --->>>
+
+
+ The DV hardware is currently transmitting the data in frame 1.
+ Once frame 1 is finished, it will automatically transmit frame 2.
+ (if frame 2 finishes before frame 3 is submitted, the device
+ will continue to transmit frame 2, and will increase the dropped_frames
+ counter each time it repeats the transmission).
+
+
+ If you called DV1394_GET_STATUS at this instant, you would
+ receive the following values:
+
+ n_frames = 4
+ active_frame = 1
+ first_clear_frame = 3
+ n_clear_frames = 2
+
+ At this point, you should write new DV data into frame 3 and optionally
+ frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that
+ it may transmit the new frames.
+
+ ERROR HANDLING
+
+ An error (buffer underflow/overflow or a break in the DV stream due
+ to a 1394 bus reset) can be detected by checking the dropped_frames
+ field of struct dv1394_status (obtained through the
+ DV1394_GET_STATUS ioctl).
+
+ The best way to recover from such an error is to re-initialize
+ dv1394, either by using the DV1394_INIT ioctl call, or closing the
+ file descriptor and opening it again. (note that you must unmap all
+ ringbuffer mappings when closing the file descriptor, or else
+ dv1394 will still be considered 'in use').
+
+ MAIN LOOP
+
+ For maximum efficiency and robustness against bus errors, you are
+ advised to model the main loop of your application after the
+ following pseudo-code example:
+
+ (checks of system call return values omitted for brevity; always
+ check return values in your code!)
+
+ while( frames left ) {
+
+ struct pollfd *pfd = ...;
+
+ pfd->fd = dv1394_fd;
+ pfd->revents = 0;
+ pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive)
+
+ (add other sources of I/O here)
+
+ poll(pfd, 1, -1); (or select(); add a timeout if you want)
+
+ if(pfd->revents) {
+ struct dv1394_status status;
+
+ ioctl(dv1394_fd, DV1394_GET_STATUS, &status);
+
+ if(status.dropped_frames > 0) {
+ reset_dv1394();
+ } else {
+ for(int i = 0; i < status.n_clear_frames; i++) {
+ copy_DV_frame();
+ }
+ }
+ }
+ }
+
+ where copy_DV_frame() reads or writes on the dv1394 file descriptor
+ (read/write mode) or copies data to/from the mmap ringbuffer and
+ then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new
+ frames are availble (mmap mode).
+
+ reset_dv1394() is called in the event of a buffer
+ underflow/overflow or a halt in the DV stream (e.g. due to a 1394
+ bus reset). To guarantee recovery from the error, this function
+ should close the dv1394 file descriptor (and munmap() all
+ ringbuffer mappings, if you are using them), then re-open the
+ dv1394 device (and re-map the ringbuffer).
+
+*/
+
+
+/* maximum number of frames in the ringbuffer */
+#define DV1394_MAX_FRAMES 32
+
+/* number of *full* isochronous packets per DV frame */
+#define DV1394_NTSC_PACKETS_PER_FRAME 250
+#define DV1394_PAL_PACKETS_PER_FRAME 300
+
+/* size of one frame's worth of DV data, in bytes */
+#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME)
+#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME)
+
+
+/* ioctl() commands */
+
+enum {
+ /* I don't like using 0 as a valid ioctl() */
+ DV1394_INVALID = 0,
+
+
+ /* get the driver ready to transmit video.
+ pass a struct dv1394_init* as the parameter (see below),
+ or NULL to get default parameters */
+ DV1394_INIT,
+
+
+ /* stop transmitting video and free the ringbuffer */
+ DV1394_SHUTDOWN,
+
+
+ /* submit N new frames to be transmitted, where
+ the index of the first new frame is first_clear_buffer,
+ and the index of the last new frame is
+ (first_clear_buffer + N) % n_frames */
+ DV1394_SUBMIT_FRAMES,
+
+
+ /* block until N buffers are clear (pass N as the parameter)
+ Because we re-transmit the last frame on underrun, there
+ will at most be n_frames - 1 clear frames at any time */
+ DV1394_WAIT_FRAMES,
+
+ /* capture new frames that have been received, where
+ the index of the first new frame is first_clear_buffer,
+ and the index of the last new frame is
+ (first_clear_buffer + N) % n_frames */
+ DV1394_RECEIVE_FRAMES,
+
+
+ DV1394_START_RECEIVE,
+
+
+ /* pass a struct dv1394_status* as the parameter (see below) */
+ DV1394_GET_STATUS,
+};
+
+
+
+enum pal_or_ntsc {
+ DV1394_NTSC = 0,
+ DV1394_PAL
+};
+
+
+
+
+/* this is the argument to DV1394_INIT */
+struct dv1394_init {
+ /* DV1394_API_VERSION */
+ unsigned int api_version;
+
+ /* isochronous transmission channel to use */
+ unsigned int channel;
+
+ /* number of frames in the ringbuffer. Must be at least 2
+ and at most DV1394_MAX_FRAMES. */
+ unsigned int n_frames;
+
+ /* send/receive PAL or NTSC video format */
+ enum pal_or_ntsc format;
+
+ /* the following are used only for transmission */
+
+ /* set these to zero unless you want a
+ non-default empty packet rate (see below) */
+ unsigned long cip_n;
+ unsigned long cip_d;
+
+ /* set this to zero unless you want a
+ non-default SYT cycle offset (default = 3 cycles) */
+ unsigned int syt_offset;
+};
+
+/* NOTE: you may only allocate the DV frame ringbuffer once each time
+ you open the dv1394 device. DV1394_INIT will fail if you call it a
+ second time with different 'n_frames' or 'format' arguments (which
+ would imply a different size for the ringbuffer). If you need a
+ different buffer size, simply close and re-open the device, then
+ initialize it with your new settings. */
+
+/* Q: What are cip_n and cip_d? */
+
+/*
+ A: DV video streams do not utilize 100% of the potential bandwidth offered
+ by IEEE 1394 (FireWire). To achieve the correct rate of data transmission,
+ DV devices must periodically insert empty packets into the 1394 data stream.
+ Typically there is one empty packet per 14-16 data-carrying packets.
+
+ Some DV devices will accept a wide range of empty packet rates, while others
+ require a precise rate. If the dv1394 driver produces empty packets at
+ a rate that your device does not accept, you may see ugly patterns on the
+ DV output, or even no output at all.
+
+ The default empty packet insertion rate seems to work for many people; if
+ your DV output is stable, you can simply ignore this discussion. However,
+ we have exposed the empty packet rate as a parameter to support devices that
+ do not work with the default rate.
+
+ The decision to insert an empty packet is made with a numerator/denominator
+ algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D.
+ You can alter the empty packet rate by passing non-zero values for cip_n
+ and cip_d to the INIT ioctl.
+
+ */
+
+
+
+struct dv1394_status {
+ /* this embedded init struct returns the current dv1394
+ parameters in use */
+ struct dv1394_init init;
+
+ /* the ringbuffer frame that is currently being
+ displayed. (-1 if the device is not transmitting anything) */
+ int active_frame;
+
+ /* index of the first buffer (ahead of active_frame) that
+ is ready to be filled with data */
+ unsigned int first_clear_frame;
+
+ /* how many buffers, including first_clear_buffer, are
+ ready to be filled with data */
+ unsigned int n_clear_frames;
+
+ /* how many times the DV stream has underflowed, overflowed,
+ or otherwise encountered an error, since the previous call
+ to DV1394_GET_STATUS */
+ unsigned int dropped_frames;
+
+ /* N.B. The dropped_frames counter is only a lower bound on the actual
+ number of dropped frames, with the special case that if dropped_frames
+ is zero, then it is guaranteed that NO frames have been dropped
+ since the last call to DV1394_GET_STATUS.
+ */
+};
+
+
+#endif /* _DV_1394_H */
diff --git a/libavformat/grab.c b/libavformat/grab.c
index 8173bac369..263c2946b9 100644
--- a/libavformat/grab.c
+++ b/libavformat/grab.c
@@ -53,8 +53,6 @@ static int aiw_init(VideoData *s);
static int aiw_read_picture(VideoData *s, uint8_t *data);
static int aiw_close(VideoData *s);
-const char *v4l_device = "/dev/video";
-
static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
{
VideoData *s = s1->priv_data;
@@ -80,9 +78,9 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
s->height = height;
s->frame_rate = frame_rate;
- video_fd = open(v4l_device, O_RDWR);
+ video_fd = open(video_device, O_RDWR);
if (video_fd < 0) {
- perror(v4l_device);
+ perror(video_device);
goto fail;
}
@@ -339,7 +337,7 @@ static int grab_read_close(AVFormatContext *s1)
}
static AVInputFormat video_grab_device_format = {
- "video_grab_device",
+ "video4linux",
"video grab",
sizeof(VideoData),
NULL,