From 8aa3ee32c257541a91bab1e47364f4f655e9e69d Mon Sep 17 00:00:00 2001 From: Max Krasnyansky Date: Wed, 22 Jan 2003 22:40:52 +0000 Subject: [PATCH] dv patch by Max Krasnyansky (maxk at qualcomm dot com) Originally committed as revision 1493 to svn://svn.ffmpeg.org/ffmpeg/trunk --- configure | 19 +++ ffmpeg.c | 21 ++- libavformat/Makefile | 4 + libavformat/allformats.c | 6 + libavformat/dv1394.c | 249 +++++++++++++++++++++++++++ libavformat/dv1394.h | 353 +++++++++++++++++++++++++++++++++++++++ libavformat/grab.c | 8 +- 7 files changed, 648 insertions(+), 12 deletions(-) create mode 100644 libavformat/dv1394.c create mode 100644 libavformat/dv1394.h 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 + * + * 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 +#include +#include +#include +#include +#include +#include + +#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 + * receive, proc_fs by Dan Dennedy + * + * based on: + * video1394.h - driver for OHCI 1394 boards + * Copyright (C)1999,2000 Sebastien Rougeaux + * Peter Schlaile + * + * 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( , buf, DV1394_NTSC_FRAME_SIZE ); + write( , 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 | + *--------------------------------------* + + + 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,