Originally committed as revision 1493 to svn://svn.ffmpeg.org/ffmpeg/trunk
Max Krasnyansky authored on 2003/01/23 07:40:52... | ... |
@@ -53,6 +53,7 @@ gprof="no" |
53 | 53 |
v4l="yes" |
54 | 54 |
audio_oss="yes" |
55 | 55 |
audio_beos="no" |
56 |
+dv1394="yes" |
|
56 | 57 |
network="yes" |
57 | 58 |
zlib="yes" |
58 | 59 |
mp3lame="no" |
... | ... |
@@ -103,6 +104,7 @@ SHFLAGS=-nostart |
103 | 103 |
# disable linux things |
104 | 104 |
audio_oss="no" |
105 | 105 |
v4l="no" |
106 |
+dv1394="no" |
|
106 | 107 |
# enable beos things |
107 | 108 |
audio_beos="yes" |
108 | 109 |
# no need for libm, but the inet stuff |
... | ... |
@@ -117,6 +119,7 @@ fi ;; |
117 | 117 |
SunOS) |
118 | 118 |
v4l="no" |
119 | 119 |
audio_oss="no" |
120 |
+dv1394="no" |
|
120 | 121 |
make="gmake" |
121 | 122 |
LDFLAGS="" |
122 | 123 |
FFSLDFLAGS="" |
... | ... |
@@ -126,12 +129,14 @@ extralibs="$extralibs -lsocket -lnsl" |
126 | 126 |
FreeBSD) |
127 | 127 |
v4l="no" |
128 | 128 |
audio_oss="yes" |
129 |
+dv1394="no" |
|
129 | 130 |
make="gmake" |
130 | 131 |
LDFLAGS="$LDFLAGS -export-dynamic" |
131 | 132 |
;; |
132 | 133 |
BSD/OS) |
133 | 134 |
v4l="no" |
134 | 135 |
audio_oss="yes" |
136 |
+dv1394="no" |
|
135 | 137 |
extralibs="-lpoll -lgnugetopt -lm" |
136 | 138 |
make="gmake" |
137 | 139 |
;; |
... | ... |
@@ -139,6 +144,7 @@ Darwin) |
139 | 139 |
cc="cc" |
140 | 140 |
v4l="no" |
141 | 141 |
audio_oss="no" |
142 |
+dv1394="no" |
|
142 | 143 |
SHFLAGS="-dynamiclib" |
143 | 144 |
extralibs="" |
144 | 145 |
darwin="yes" |
... | ... |
@@ -158,6 +164,7 @@ esac |
158 | 158 |
MINGW32*) |
159 | 159 |
v4l="no" |
160 | 160 |
audio_oss="no" |
161 |
+dv1394="no" |
|
161 | 162 |
ffserver="no" |
162 | 163 |
network="no" |
163 | 164 |
mingw32="yes" |
... | ... |
@@ -165,6 +172,7 @@ mingw32="yes" |
165 | 165 |
CYGWIN*) |
166 | 166 |
v4l="no" |
167 | 167 |
audio_oss="yes" |
168 |
+dv1394="no" |
|
168 | 169 |
extralibs="" |
169 | 170 |
cygwin="yes" |
170 | 171 |
test -f /usr/include/inttypes.h || \ |
... | ... |
@@ -190,6 +198,7 @@ SLIBSUF=".dll" |
190 | 190 |
extralibs="" |
191 | 191 |
v4l="no" |
192 | 192 |
audio_oss="no" |
193 |
+dv1394="no" |
|
193 | 194 |
network="no" |
194 | 195 |
ffserver="no" |
195 | 196 |
os2="yes" |
... | ... |
@@ -287,6 +296,8 @@ for opt do |
287 | 287 |
;; |
288 | 288 |
--disable-audio-beos) audio_beos="no" |
289 | 289 |
;; |
290 |
+ --disable-dv1394) dv1394="no" |
|
291 |
+ ;; |
|
290 | 292 |
--disable-network) network="no" |
291 | 293 |
;; |
292 | 294 |
--disable-zlib) zlib="no" |
... | ... |
@@ -375,6 +386,7 @@ if test "$win32" = "yes" ; then |
375 | 375 |
cross_prefix="i386-mingw32msvc-" |
376 | 376 |
v4l="no" |
377 | 377 |
audio_oss="no" |
378 |
+ dv1394="no" |
|
378 | 379 |
network="no" |
379 | 380 |
fi |
380 | 381 |
|
... | ... |
@@ -382,6 +394,7 @@ if test "$mingw32" = "yes" ; then |
382 | 382 |
cross_prefix="" |
383 | 383 |
v4l="no" |
384 | 384 |
audio_oss="no" |
385 |
+ dv1394="no" |
|
385 | 386 |
network="no" |
386 | 387 |
fi |
387 | 388 |
|
... | ... |
@@ -543,6 +556,7 @@ echo " --disable-altivec disable AltiVec usage" |
543 | 543 |
echo " --disable-audio-oss disable OSS audio support [default=no]" |
544 | 544 |
echo " --disable-audio-beos disable BeOS audio support [default=no]" |
545 | 545 |
echo " --disable-v4l disable video4linux grabbing [default=no]" |
546 |
+echo " --disable-dv1394 disable DV1394 grabbing [default=no]" |
|
546 | 547 |
echo " --disable-network disable network support [default=no]" |
547 | 548 |
echo " --disable-zlib disable zlib [default=no]" |
548 | 549 |
echo " --disable-simple_idct disable simple IDCT routines [default=no]" |
... | ... |
@@ -705,6 +719,11 @@ if test "$v4l" = "yes" ; then |
705 | 705 |
echo "CONFIG_VIDEO4LINUX=yes" >> config.mak |
706 | 706 |
fi |
707 | 707 |
|
708 |
+if test "$dv1394" = "yes" ; then |
|
709 |
+ echo "#define CONFIG_DV1394 1" >> $TMPH |
|
710 |
+ echo "CONFIG_DV1394=yes" >> config.mak |
|
711 |
+fi |
|
712 |
+ |
|
708 | 713 |
if test "$dlopen" = "yes" ; then |
709 | 714 |
echo "#define CONFIG_HAVE_DLOPEN 1" >> $TMPH |
710 | 715 |
fi |
... | ... |
@@ -158,14 +158,14 @@ static char *pass_logfilename = NULL; |
158 | 158 |
static int audio_stream_copy = 0; |
159 | 159 |
static int video_stream_copy = 0; |
160 | 160 |
|
161 |
+static char *video_grab_format = "video4linux"; |
|
162 |
+static char *audio_grab_format = "audio_device"; |
|
163 |
+ |
|
161 | 164 |
#define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass" |
162 | 165 |
|
163 | 166 |
#if !defined(CONFIG_AUDIO_OSS) && !defined(CONFIG_AUDIO_BEOS) |
164 | 167 |
const char *audio_device = "none"; |
165 | 168 |
#endif |
166 |
-#ifndef CONFIG_VIDEO4LINUX |
|
167 |
-const char *v4l_device = "none"; |
|
168 |
-#endif |
|
169 | 169 |
|
170 | 170 |
typedef struct AVOutputStream { |
171 | 171 |
int file_index; /* file index */ |
... | ... |
@@ -1870,7 +1870,7 @@ void opt_audio_channels(const char *arg) |
1870 | 1870 |
|
1871 | 1871 |
void opt_video_device(const char *arg) |
1872 | 1872 |
{ |
1873 |
- v4l_device = strdup(arg); |
|
1873 |
+ video_device = strdup(arg); |
|
1874 | 1874 |
} |
1875 | 1875 |
|
1876 | 1876 |
void opt_audio_device(const char *arg) |
... | ... |
@@ -1878,6 +1878,12 @@ void opt_audio_device(const char *arg) |
1878 | 1878 |
audio_device = strdup(arg); |
1879 | 1879 |
} |
1880 | 1880 |
|
1881 |
+void opt_dv1394(const char *arg) |
|
1882 |
+{ |
|
1883 |
+ video_grab_format = "dv1394"; |
|
1884 |
+ audio_grab_format = "none"; |
|
1885 |
+} |
|
1886 |
+ |
|
1881 | 1887 |
void opt_audio_codec(const char *arg) |
1882 | 1888 |
{ |
1883 | 1889 |
AVCodec *p; |
... | ... |
@@ -2455,7 +2461,7 @@ void prepare_grab(void) |
2455 | 2455 |
|
2456 | 2456 |
if (has_video) { |
2457 | 2457 |
AVInputFormat *fmt1; |
2458 |
- fmt1 = av_find_input_format("video_grab_device"); |
|
2458 |
+ fmt1 = av_find_input_format(video_grab_format); |
|
2459 | 2459 |
if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) { |
2460 | 2460 |
fprintf(stderr, "Could not find video grab device\n"); |
2461 | 2461 |
exit(1); |
... | ... |
@@ -2463,12 +2469,12 @@ void prepare_grab(void) |
2463 | 2463 |
/* by now video grab has one stream */ |
2464 | 2464 |
ic->streams[0]->r_frame_rate = ap->frame_rate; |
2465 | 2465 |
input_files[nb_input_files] = ic; |
2466 |
- dump_format(ic, nb_input_files, v4l_device, 0); |
|
2466 |
+ dump_format(ic, nb_input_files, video_device, 0); |
|
2467 | 2467 |
nb_input_files++; |
2468 | 2468 |
} |
2469 | 2469 |
if (has_audio) { |
2470 | 2470 |
AVInputFormat *fmt1; |
2471 |
- fmt1 = av_find_input_format("audio_device"); |
|
2471 |
+ fmt1 = av_find_input_format(audio_grab_format); |
|
2472 | 2472 |
if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) { |
2473 | 2473 |
fprintf(stderr, "Could not find audio grab device\n"); |
2474 | 2474 |
exit(1); |
... | ... |
@@ -2692,6 +2698,7 @@ const OptionDef options[] = { |
2692 | 2692 |
{ "minrate", HAS_ARG, {(void*)opt_video_bitrate_min}, "set min video bitrate tolerance (in kbit/s)", "bitrate" }, |
2693 | 2693 |
{ "bufsize", HAS_ARG, {(void*)opt_video_buffer_size}, "set ratecontrol buffere size (in kbit)", "size" }, |
2694 | 2694 |
{ "vd", HAS_ARG | OPT_EXPERT, {(void*)opt_video_device}, "set video grab device", "device" }, |
2695 |
+ { "dv1394", OPT_EXPERT, {(void*)opt_dv1394}, "set DV1394 options", "[channel]" }, |
|
2695 | 2696 |
{ "vcodec", HAS_ARG | OPT_EXPERT, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" }, |
2696 | 2697 |
{ "me", HAS_ARG | OPT_EXPERT, {(void*)opt_motion_estimation}, "set motion estimation method", |
2697 | 2698 |
"method" }, |
... | ... |
@@ -21,6 +21,8 @@ |
21 | 21 |
/* If you do not call this function, then you can select exactly which |
22 | 22 |
formats you want to support */ |
23 | 23 |
|
24 |
+char *video_device = "none"; |
|
25 |
+ |
|
24 | 26 |
/** |
25 | 27 |
* Initialize libavcodec and register all the codecs and formats. |
26 | 28 |
*/ |
... | ... |
@@ -62,6 +64,10 @@ void av_register_all(void) |
62 | 62 |
audio_init(); |
63 | 63 |
#endif |
64 | 64 |
|
65 |
+#ifdef CONFIG_DV1394 |
|
66 |
+ dv1394_init(); |
|
67 |
+#endif |
|
68 |
+ |
|
65 | 69 |
/* image formats */ |
66 | 70 |
av_register_image_format(&pnm_image_format); |
67 | 71 |
av_register_image_format(&pbm_image_format); |
68 | 72 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,249 @@ |
0 |
+/* |
|
1 |
+ * Linux DV1394 interface |
|
2 |
+ * Copyright (c) 2003 Max Krasnyansky <maxk@qualcomm.com> |
|
3 |
+ * |
|
4 |
+ * This library is free software; you can redistribute it and/or |
|
5 |
+ * modify it under the terms of the GNU Lesser General Public |
|
6 |
+ * License as published by the Free Software Foundation; either |
|
7 |
+ * version 2 of the License, or (at your option) any later version. |
|
8 |
+ * |
|
9 |
+ * This library is distributed in the hope that it will be useful, |
|
10 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 |
+ * Lesser General Public License for more details. |
|
13 |
+ * |
|
14 |
+ * You should have received a copy of the GNU Lesser General Public |
|
15 |
+ * License along with this library; if not, write to the Free Software |
|
16 |
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 |
+ */ |
|
18 |
+ |
|
19 |
+#include <unistd.h> |
|
20 |
+#include <fcntl.h> |
|
21 |
+#include <sys/ioctl.h> |
|
22 |
+#include <sys/mman.h> |
|
23 |
+#include <sys/poll.h> |
|
24 |
+#include <sys/time.h> |
|
25 |
+#include <time.h> |
|
26 |
+ |
|
27 |
+#include "avformat.h" |
|
28 |
+ |
|
29 |
+#undef DV1394_DEBUG |
|
30 |
+ |
|
31 |
+#include "dv1394.h" |
|
32 |
+ |
|
33 |
+int dv1394_channel = DV1394_DEFAULT_CHANNEL; |
|
34 |
+ |
|
35 |
+struct dv1394_data { |
|
36 |
+ int fd; |
|
37 |
+ int channel; |
|
38 |
+ int width, height; |
|
39 |
+ int frame_rate; |
|
40 |
+ int frame_size; |
|
41 |
+ |
|
42 |
+ void *ring; /* Ring buffer */ |
|
43 |
+ int index; /* Current frame index */ |
|
44 |
+ int avail; /* Number of frames available for reading */ |
|
45 |
+ int done; /* Number of completed frames */ |
|
46 |
+}; |
|
47 |
+ |
|
48 |
+static int dv1394_reset(struct dv1394_data *dv) |
|
49 |
+{ |
|
50 |
+ struct dv1394_init init; |
|
51 |
+ |
|
52 |
+ init.channel = dv->channel; |
|
53 |
+ init.api_version = DV1394_API_VERSION; |
|
54 |
+ init.n_frames = DV1394_RING_FRAMES; |
|
55 |
+ init.format = DV1394_NTSC; |
|
56 |
+ |
|
57 |
+ if (ioctl(dv->fd, DV1394_INIT, &init) < 0) |
|
58 |
+ return -1; |
|
59 |
+ |
|
60 |
+ dv->avail = 0; |
|
61 |
+ return 0; |
|
62 |
+} |
|
63 |
+ |
|
64 |
+static int dv1394_start(struct dv1394_data *dv) |
|
65 |
+{ |
|
66 |
+ /* Tell DV1394 driver to enable receiver */ |
|
67 |
+ if (ioctl(dv->fd, DV1394_START_RECEIVE, 0) < 0) { |
|
68 |
+ perror("Failed to start receiver"); |
|
69 |
+ return -1; |
|
70 |
+ } |
|
71 |
+ return 0; |
|
72 |
+} |
|
73 |
+ |
|
74 |
+static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap) |
|
75 |
+{ |
|
76 |
+ struct dv1394_data *dv = context->priv_data; |
|
77 |
+ AVStream *st; |
|
78 |
+ |
|
79 |
+ st = av_new_stream(context, 0); |
|
80 |
+ if (!st) |
|
81 |
+ return -ENOMEM; |
|
82 |
+ |
|
83 |
+ dv->width = DV1394_WIDTH; |
|
84 |
+ dv->height = DV1394_HEIGHT; |
|
85 |
+ dv->channel = dv1394_channel; |
|
86 |
+ |
|
87 |
+ dv->frame_rate = 30; |
|
88 |
+ |
|
89 |
+ dv->frame_size = DV1394_NTSC_FRAME_SIZE; |
|
90 |
+ |
|
91 |
+ /* Open and initialize DV1394 device */ |
|
92 |
+ |
|
93 |
+ dv->fd = open(video_device, O_RDONLY); |
|
94 |
+ if (dv->fd < 0) { |
|
95 |
+ perror("Failed to open DV interface"); |
|
96 |
+ goto failed; |
|
97 |
+ } |
|
98 |
+ |
|
99 |
+ if (dv1394_reset(dv) < 0) { |
|
100 |
+ perror("Failed to initialize DV interface"); |
|
101 |
+ goto failed; |
|
102 |
+ } |
|
103 |
+ |
|
104 |
+ dv->ring = mmap(NULL, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES, |
|
105 |
+ PROT_READ, MAP_PRIVATE, dv->fd, 0); |
|
106 |
+ if (!dv->ring) { |
|
107 |
+ perror("Failed to mmap DV ring buffer"); |
|
108 |
+ goto failed; |
|
109 |
+ } |
|
110 |
+ |
|
111 |
+ st->codec.codec_type = CODEC_TYPE_VIDEO; |
|
112 |
+ st->codec.codec_id = CODEC_ID_DVVIDEO; |
|
113 |
+ st->codec.width = dv->width; |
|
114 |
+ st->codec.height = dv->height; |
|
115 |
+ st->codec.frame_rate = dv->frame_rate * FRAME_RATE_BASE; |
|
116 |
+ |
|
117 |
+ st->codec.bit_rate = 25000000; /* Consumer DV is 25Mbps */ |
|
118 |
+ |
|
119 |
+ av_set_pts_info(context, 48, 1, 1000000); |
|
120 |
+ |
|
121 |
+ if (dv1394_start(dv) < 0) |
|
122 |
+ goto failed; |
|
123 |
+ |
|
124 |
+ return 0; |
|
125 |
+ |
|
126 |
+failed: |
|
127 |
+ close(dv->fd); |
|
128 |
+ av_free(st); |
|
129 |
+ return -EIO; |
|
130 |
+} |
|
131 |
+ |
|
132 |
+static inline int __copy_frame(struct dv1394_data *dv, void *buf) |
|
133 |
+{ |
|
134 |
+ char *ptr = dv->ring + (dv->index * dv->frame_size); |
|
135 |
+ |
|
136 |
+ memcpy(buf, ptr, dv->frame_size); |
|
137 |
+ |
|
138 |
+ dv->index = (dv->index + 1) % DV1394_RING_FRAMES; |
|
139 |
+ dv->avail--; |
|
140 |
+ dv->done++; |
|
141 |
+ |
|
142 |
+ return dv->frame_size; |
|
143 |
+} |
|
144 |
+ |
|
145 |
+static int dv1394_read_packet(AVFormatContext * context, AVPacket * pkt) |
|
146 |
+{ |
|
147 |
+ struct dv1394_data *dv = context->priv_data; |
|
148 |
+ int len; |
|
149 |
+ |
|
150 |
+ if (!dv->avail) { |
|
151 |
+ struct dv1394_status s; |
|
152 |
+ struct pollfd p; |
|
153 |
+ p.fd = dv->fd; |
|
154 |
+ p.events = POLLIN | POLLERR | POLLHUP; |
|
155 |
+ |
|
156 |
+ /* Wait until more frames are available */ |
|
157 |
+ if (poll(&p, 1, -1) < 0) { |
|
158 |
+ perror("Poll failed"); |
|
159 |
+ return -EIO; |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ if (ioctl(dv->fd, DV1394_GET_STATUS, &s) < 0) { |
|
163 |
+ perror("Failed to get status"); |
|
164 |
+ return -EIO; |
|
165 |
+ } |
|
166 |
+#ifdef DV1394_DEBUG |
|
167 |
+ fprintf(stderr, "DV1394: status\n" |
|
168 |
+ "\tactive_frame\t%d\n" |
|
169 |
+ "\tfirst_clear_frame\t%d\n" |
|
170 |
+ "\tn_clear_frames\t%d\n" |
|
171 |
+ "\tdropped_frames\t%d\n", |
|
172 |
+ s.active_frame, s.first_clear_frame, |
|
173 |
+ s.n_clear_frames, s.dropped_frames); |
|
174 |
+#endif |
|
175 |
+ |
|
176 |
+ dv->avail = s.n_clear_frames; |
|
177 |
+ dv->index = s.first_clear_frame; |
|
178 |
+ dv->done = 0; |
|
179 |
+ |
|
180 |
+ if (s.dropped_frames) { |
|
181 |
+ fprintf(stderr, "DV1394: Frame drop detected (%d). Reseting ..\n", |
|
182 |
+ s.dropped_frames); |
|
183 |
+ |
|
184 |
+ dv1394_reset(dv); |
|
185 |
+ dv1394_start(dv); |
|
186 |
+ } |
|
187 |
+ } |
|
188 |
+ |
|
189 |
+ if (av_new_packet(pkt, dv->frame_size) < 0) |
|
190 |
+ return -EIO; |
|
191 |
+ |
|
192 |
+#ifdef DV1394_DEBUG |
|
193 |
+ fprintf(stderr, "index %d, avail %d, done %d\n", dv->index, dv->avail, |
|
194 |
+ dv->done); |
|
195 |
+#endif |
|
196 |
+ |
|
197 |
+ len = __copy_frame(dv, pkt->data); |
|
198 |
+ pkt->pts = av_gettime() & ((1LL << 48) - 1); |
|
199 |
+ |
|
200 |
+ if (!dv->avail && dv->done) { |
|
201 |
+ /* Request more frames */ |
|
202 |
+ if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) { |
|
203 |
+ /* This usually means that ring buffer overflowed. |
|
204 |
+ * We have to reset :(. |
|
205 |
+ */ |
|
206 |
+ |
|
207 |
+ fprintf(stderr, "DV1394: Ring buffer overflow. Reseting ..\n"); |
|
208 |
+ |
|
209 |
+ dv1394_reset(dv); |
|
210 |
+ dv1394_start(dv); |
|
211 |
+ } |
|
212 |
+ } |
|
213 |
+ |
|
214 |
+ return len; |
|
215 |
+} |
|
216 |
+ |
|
217 |
+static int dv1394_close(AVFormatContext * context) |
|
218 |
+{ |
|
219 |
+ struct dv1394_data *dv = context->priv_data; |
|
220 |
+ |
|
221 |
+ /* Shutdown DV1394 receiver */ |
|
222 |
+ if (ioctl(dv->fd, DV1394_SHUTDOWN, 0) < 0) |
|
223 |
+ perror("Failed to shutdown DV1394"); |
|
224 |
+ |
|
225 |
+ /* Unmap ring buffer */ |
|
226 |
+ if (munmap(dv->ring, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES) < 0) |
|
227 |
+ perror("Failed to munmap DV1394 ring buffer"); |
|
228 |
+ |
|
229 |
+ close(dv->fd); |
|
230 |
+ |
|
231 |
+ return 0; |
|
232 |
+} |
|
233 |
+ |
|
234 |
+static AVInputFormat dv1394_format = { |
|
235 |
+ .name = "dv1394", |
|
236 |
+ .long_name = "dv1394 A/V grab", |
|
237 |
+ .priv_data_size = sizeof(struct dv1394_data), |
|
238 |
+ .read_header = dv1394_read_header, |
|
239 |
+ .read_packet = dv1394_read_packet, |
|
240 |
+ .read_close = dv1394_close, |
|
241 |
+ .flags = AVFMT_NOFILE |
|
242 |
+}; |
|
243 |
+ |
|
244 |
+int dv1394_init(void) |
|
245 |
+{ |
|
246 |
+ av_register_input_format(&dv1394_format); |
|
247 |
+ return 0; |
|
248 |
+} |
0 | 249 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,353 @@ |
0 |
+/* |
|
1 |
+ * dv1394.h - DV input/output over IEEE 1394 on OHCI chips |
|
2 |
+ * Copyright (C)2001 Daniel Maas <dmaas@dcine.com> |
|
3 |
+ * receive, proc_fs by Dan Dennedy <dan@dennedy.org> |
|
4 |
+ * |
|
5 |
+ * based on: |
|
6 |
+ * video1394.h - driver for OHCI 1394 boards |
|
7 |
+ * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au> |
|
8 |
+ * Peter Schlaile <udbz@rz.uni-karlsruhe.de> |
|
9 |
+ * |
|
10 |
+ * This program is free software; you can redistribute it and/or modify |
|
11 |
+ * it under the terms of the GNU General Public License as published by |
|
12 |
+ * the Free Software Foundation; either version 2 of the License, or |
|
13 |
+ * (at your option) any later version. |
|
14 |
+ * |
|
15 |
+ * This program is distributed in the hope that it will be useful, |
|
16 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
17 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
18 |
+ * GNU General Public License for more details. |
|
19 |
+ * |
|
20 |
+ * You should have received a copy of the GNU General Public License |
|
21 |
+ * along with this program; if not, write to the Free Software Foundation, |
|
22 |
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+#ifndef _DV_1394_H |
|
26 |
+#define _DV_1394_H |
|
27 |
+ |
|
28 |
+#define DV1394_DEFAULT_CHANNEL 0x63 |
|
29 |
+#define DV1394_DEFAULT_CARD 0 |
|
30 |
+#define DV1394_RING_FRAMES 20 |
|
31 |
+ |
|
32 |
+#define DV1394_WIDTH 720 |
|
33 |
+#define DV1394_HEIGHT 480 |
|
34 |
+ |
|
35 |
+/* This is the public user-space interface. Try not to break it. */ |
|
36 |
+ |
|
37 |
+#define DV1394_API_VERSION 0x20011127 |
|
38 |
+ |
|
39 |
+/* ******************** |
|
40 |
+ ** ** |
|
41 |
+ ** DV1394 API ** |
|
42 |
+ ** ** |
|
43 |
+ ******************** |
|
44 |
+ |
|
45 |
+ There are two methods of operating the DV1394 DV output device. |
|
46 |
+ |
|
47 |
+ 1) |
|
48 |
+ |
|
49 |
+ The simplest is an interface based on write(): simply write |
|
50 |
+ full DV frames of data to the device, and they will be transmitted |
|
51 |
+ as quickly as possible. The FD may be set for non-blocking I/O, |
|
52 |
+ in which case you can use select() or poll() to wait for output |
|
53 |
+ buffer space. |
|
54 |
+ |
|
55 |
+ To set the DV output parameters (e.g. whether you want NTSC or PAL |
|
56 |
+ video), use the DV1394_INIT ioctl, passing in the parameters you |
|
57 |
+ want in a struct dv1394_init. |
|
58 |
+ |
|
59 |
+ Example 1: |
|
60 |
+ To play a raw .DV file: cat foo.DV > /dev/dv1394 |
|
61 |
+ (cat will use write() internally) |
|
62 |
+ |
|
63 |
+ Example 2: |
|
64 |
+ static struct dv1394_init init = { |
|
65 |
+ 0x63, (broadcast channel) |
|
66 |
+ 4, (four-frame ringbuffer) |
|
67 |
+ DV1394_NTSC, (send NTSC video) |
|
68 |
+ 0, 0 (default empty packet rate) |
|
69 |
+ } |
|
70 |
+ |
|
71 |
+ ioctl(fd, DV1394_INIT, &init); |
|
72 |
+ |
|
73 |
+ while(1) { |
|
74 |
+ read( <a raw DV file>, buf, DV1394_NTSC_FRAME_SIZE ); |
|
75 |
+ write( <the dv1394 FD>, buf, DV1394_NTSC_FRAME_SIZE ); |
|
76 |
+ } |
|
77 |
+ |
|
78 |
+ 2) |
|
79 |
+ |
|
80 |
+ For more control over buffering, and to avoid unnecessary copies |
|
81 |
+ of the DV data, you can use the more sophisticated the mmap() interface. |
|
82 |
+ First, call the DV1394_INIT ioctl to specify your parameters, |
|
83 |
+ including the number of frames in the ringbuffer. Then, calling mmap() |
|
84 |
+ on the dv1394 device will give you direct access to the ringbuffer |
|
85 |
+ from which the DV card reads your frame data. |
|
86 |
+ |
|
87 |
+ The ringbuffer is simply one large, contiguous region of memory |
|
88 |
+ containing two or more frames of packed DV data. Each frame of DV data |
|
89 |
+ is 120000 bytes (NTSC) or 144000 bytes (PAL). |
|
90 |
+ |
|
91 |
+ Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES |
|
92 |
+ ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl |
|
93 |
+ or select()/poll() to wait until the frames are transmitted. Next, you'll |
|
94 |
+ need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer |
|
95 |
+ frames are clear (ready to be filled with new DV data). Finally, use |
|
96 |
+ DV1394_SUBMIT_FRAMES again to send the new data to the DV output. |
|
97 |
+ |
|
98 |
+ |
|
99 |
+ Example: here is what a four-frame ringbuffer might look like |
|
100 |
+ during DV transmission: |
|
101 |
+ |
|
102 |
+ |
|
103 |
+ frame 0 frame 1 frame 2 frame 3 |
|
104 |
+ |
|
105 |
+ *--------------------------------------* |
|
106 |
+ | CLEAR | DV data | DV data | CLEAR | |
|
107 |
+ *--------------------------------------* |
|
108 |
+ <ACTIVE> |
|
109 |
+ |
|
110 |
+ transmission goes in this direction --->>> |
|
111 |
+ |
|
112 |
+ |
|
113 |
+ The DV hardware is currently transmitting the data in frame 1. |
|
114 |
+ Once frame 1 is finished, it will automatically transmit frame 2. |
|
115 |
+ (if frame 2 finishes before frame 3 is submitted, the device |
|
116 |
+ will continue to transmit frame 2, and will increase the dropped_frames |
|
117 |
+ counter each time it repeats the transmission). |
|
118 |
+ |
|
119 |
+ |
|
120 |
+ If you called DV1394_GET_STATUS at this instant, you would |
|
121 |
+ receive the following values: |
|
122 |
+ |
|
123 |
+ n_frames = 4 |
|
124 |
+ active_frame = 1 |
|
125 |
+ first_clear_frame = 3 |
|
126 |
+ n_clear_frames = 2 |
|
127 |
+ |
|
128 |
+ At this point, you should write new DV data into frame 3 and optionally |
|
129 |
+ frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that |
|
130 |
+ it may transmit the new frames. |
|
131 |
+ |
|
132 |
+ ERROR HANDLING |
|
133 |
+ |
|
134 |
+ An error (buffer underflow/overflow or a break in the DV stream due |
|
135 |
+ to a 1394 bus reset) can be detected by checking the dropped_frames |
|
136 |
+ field of struct dv1394_status (obtained through the |
|
137 |
+ DV1394_GET_STATUS ioctl). |
|
138 |
+ |
|
139 |
+ The best way to recover from such an error is to re-initialize |
|
140 |
+ dv1394, either by using the DV1394_INIT ioctl call, or closing the |
|
141 |
+ file descriptor and opening it again. (note that you must unmap all |
|
142 |
+ ringbuffer mappings when closing the file descriptor, or else |
|
143 |
+ dv1394 will still be considered 'in use'). |
|
144 |
+ |
|
145 |
+ MAIN LOOP |
|
146 |
+ |
|
147 |
+ For maximum efficiency and robustness against bus errors, you are |
|
148 |
+ advised to model the main loop of your application after the |
|
149 |
+ following pseudo-code example: |
|
150 |
+ |
|
151 |
+ (checks of system call return values omitted for brevity; always |
|
152 |
+ check return values in your code!) |
|
153 |
+ |
|
154 |
+ while( frames left ) { |
|
155 |
+ |
|
156 |
+ struct pollfd *pfd = ...; |
|
157 |
+ |
|
158 |
+ pfd->fd = dv1394_fd; |
|
159 |
+ pfd->revents = 0; |
|
160 |
+ pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive) |
|
161 |
+ |
|
162 |
+ (add other sources of I/O here) |
|
163 |
+ |
|
164 |
+ poll(pfd, 1, -1); (or select(); add a timeout if you want) |
|
165 |
+ |
|
166 |
+ if(pfd->revents) { |
|
167 |
+ struct dv1394_status status; |
|
168 |
+ |
|
169 |
+ ioctl(dv1394_fd, DV1394_GET_STATUS, &status); |
|
170 |
+ |
|
171 |
+ if(status.dropped_frames > 0) { |
|
172 |
+ reset_dv1394(); |
|
173 |
+ } else { |
|
174 |
+ for(int i = 0; i < status.n_clear_frames; i++) { |
|
175 |
+ copy_DV_frame(); |
|
176 |
+ } |
|
177 |
+ } |
|
178 |
+ } |
|
179 |
+ } |
|
180 |
+ |
|
181 |
+ where copy_DV_frame() reads or writes on the dv1394 file descriptor |
|
182 |
+ (read/write mode) or copies data to/from the mmap ringbuffer and |
|
183 |
+ then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new |
|
184 |
+ frames are availble (mmap mode). |
|
185 |
+ |
|
186 |
+ reset_dv1394() is called in the event of a buffer |
|
187 |
+ underflow/overflow or a halt in the DV stream (e.g. due to a 1394 |
|
188 |
+ bus reset). To guarantee recovery from the error, this function |
|
189 |
+ should close the dv1394 file descriptor (and munmap() all |
|
190 |
+ ringbuffer mappings, if you are using them), then re-open the |
|
191 |
+ dv1394 device (and re-map the ringbuffer). |
|
192 |
+ |
|
193 |
+*/ |
|
194 |
+ |
|
195 |
+ |
|
196 |
+/* maximum number of frames in the ringbuffer */ |
|
197 |
+#define DV1394_MAX_FRAMES 32 |
|
198 |
+ |
|
199 |
+/* number of *full* isochronous packets per DV frame */ |
|
200 |
+#define DV1394_NTSC_PACKETS_PER_FRAME 250 |
|
201 |
+#define DV1394_PAL_PACKETS_PER_FRAME 300 |
|
202 |
+ |
|
203 |
+/* size of one frame's worth of DV data, in bytes */ |
|
204 |
+#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME) |
|
205 |
+#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME) |
|
206 |
+ |
|
207 |
+ |
|
208 |
+/* ioctl() commands */ |
|
209 |
+ |
|
210 |
+enum { |
|
211 |
+ /* I don't like using 0 as a valid ioctl() */ |
|
212 |
+ DV1394_INVALID = 0, |
|
213 |
+ |
|
214 |
+ |
|
215 |
+ /* get the driver ready to transmit video. |
|
216 |
+ pass a struct dv1394_init* as the parameter (see below), |
|
217 |
+ or NULL to get default parameters */ |
|
218 |
+ DV1394_INIT, |
|
219 |
+ |
|
220 |
+ |
|
221 |
+ /* stop transmitting video and free the ringbuffer */ |
|
222 |
+ DV1394_SHUTDOWN, |
|
223 |
+ |
|
224 |
+ |
|
225 |
+ /* submit N new frames to be transmitted, where |
|
226 |
+ the index of the first new frame is first_clear_buffer, |
|
227 |
+ and the index of the last new frame is |
|
228 |
+ (first_clear_buffer + N) % n_frames */ |
|
229 |
+ DV1394_SUBMIT_FRAMES, |
|
230 |
+ |
|
231 |
+ |
|
232 |
+ /* block until N buffers are clear (pass N as the parameter) |
|
233 |
+ Because we re-transmit the last frame on underrun, there |
|
234 |
+ will at most be n_frames - 1 clear frames at any time */ |
|
235 |
+ DV1394_WAIT_FRAMES, |
|
236 |
+ |
|
237 |
+ /* capture new frames that have been received, where |
|
238 |
+ the index of the first new frame is first_clear_buffer, |
|
239 |
+ and the index of the last new frame is |
|
240 |
+ (first_clear_buffer + N) % n_frames */ |
|
241 |
+ DV1394_RECEIVE_FRAMES, |
|
242 |
+ |
|
243 |
+ |
|
244 |
+ DV1394_START_RECEIVE, |
|
245 |
+ |
|
246 |
+ |
|
247 |
+ /* pass a struct dv1394_status* as the parameter (see below) */ |
|
248 |
+ DV1394_GET_STATUS, |
|
249 |
+}; |
|
250 |
+ |
|
251 |
+ |
|
252 |
+ |
|
253 |
+enum pal_or_ntsc { |
|
254 |
+ DV1394_NTSC = 0, |
|
255 |
+ DV1394_PAL |
|
256 |
+}; |
|
257 |
+ |
|
258 |
+ |
|
259 |
+ |
|
260 |
+ |
|
261 |
+/* this is the argument to DV1394_INIT */ |
|
262 |
+struct dv1394_init { |
|
263 |
+ /* DV1394_API_VERSION */ |
|
264 |
+ unsigned int api_version; |
|
265 |
+ |
|
266 |
+ /* isochronous transmission channel to use */ |
|
267 |
+ unsigned int channel; |
|
268 |
+ |
|
269 |
+ /* number of frames in the ringbuffer. Must be at least 2 |
|
270 |
+ and at most DV1394_MAX_FRAMES. */ |
|
271 |
+ unsigned int n_frames; |
|
272 |
+ |
|
273 |
+ /* send/receive PAL or NTSC video format */ |
|
274 |
+ enum pal_or_ntsc format; |
|
275 |
+ |
|
276 |
+ /* the following are used only for transmission */ |
|
277 |
+ |
|
278 |
+ /* set these to zero unless you want a |
|
279 |
+ non-default empty packet rate (see below) */ |
|
280 |
+ unsigned long cip_n; |
|
281 |
+ unsigned long cip_d; |
|
282 |
+ |
|
283 |
+ /* set this to zero unless you want a |
|
284 |
+ non-default SYT cycle offset (default = 3 cycles) */ |
|
285 |
+ unsigned int syt_offset; |
|
286 |
+}; |
|
287 |
+ |
|
288 |
+/* NOTE: you may only allocate the DV frame ringbuffer once each time |
|
289 |
+ you open the dv1394 device. DV1394_INIT will fail if you call it a |
|
290 |
+ second time with different 'n_frames' or 'format' arguments (which |
|
291 |
+ would imply a different size for the ringbuffer). If you need a |
|
292 |
+ different buffer size, simply close and re-open the device, then |
|
293 |
+ initialize it with your new settings. */ |
|
294 |
+ |
|
295 |
+/* Q: What are cip_n and cip_d? */ |
|
296 |
+ |
|
297 |
+/* |
|
298 |
+ A: DV video streams do not utilize 100% of the potential bandwidth offered |
|
299 |
+ by IEEE 1394 (FireWire). To achieve the correct rate of data transmission, |
|
300 |
+ DV devices must periodically insert empty packets into the 1394 data stream. |
|
301 |
+ Typically there is one empty packet per 14-16 data-carrying packets. |
|
302 |
+ |
|
303 |
+ Some DV devices will accept a wide range of empty packet rates, while others |
|
304 |
+ require a precise rate. If the dv1394 driver produces empty packets at |
|
305 |
+ a rate that your device does not accept, you may see ugly patterns on the |
|
306 |
+ DV output, or even no output at all. |
|
307 |
+ |
|
308 |
+ The default empty packet insertion rate seems to work for many people; if |
|
309 |
+ your DV output is stable, you can simply ignore this discussion. However, |
|
310 |
+ we have exposed the empty packet rate as a parameter to support devices that |
|
311 |
+ do not work with the default rate. |
|
312 |
+ |
|
313 |
+ The decision to insert an empty packet is made with a numerator/denominator |
|
314 |
+ algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D. |
|
315 |
+ You can alter the empty packet rate by passing non-zero values for cip_n |
|
316 |
+ and cip_d to the INIT ioctl. |
|
317 |
+ |
|
318 |
+ */ |
|
319 |
+ |
|
320 |
+ |
|
321 |
+ |
|
322 |
+struct dv1394_status { |
|
323 |
+ /* this embedded init struct returns the current dv1394 |
|
324 |
+ parameters in use */ |
|
325 |
+ struct dv1394_init init; |
|
326 |
+ |
|
327 |
+ /* the ringbuffer frame that is currently being |
|
328 |
+ displayed. (-1 if the device is not transmitting anything) */ |
|
329 |
+ int active_frame; |
|
330 |
+ |
|
331 |
+ /* index of the first buffer (ahead of active_frame) that |
|
332 |
+ is ready to be filled with data */ |
|
333 |
+ unsigned int first_clear_frame; |
|
334 |
+ |
|
335 |
+ /* how many buffers, including first_clear_buffer, are |
|
336 |
+ ready to be filled with data */ |
|
337 |
+ unsigned int n_clear_frames; |
|
338 |
+ |
|
339 |
+ /* how many times the DV stream has underflowed, overflowed, |
|
340 |
+ or otherwise encountered an error, since the previous call |
|
341 |
+ to DV1394_GET_STATUS */ |
|
342 |
+ unsigned int dropped_frames; |
|
343 |
+ |
|
344 |
+ /* N.B. The dropped_frames counter is only a lower bound on the actual |
|
345 |
+ number of dropped frames, with the special case that if dropped_frames |
|
346 |
+ is zero, then it is guaranteed that NO frames have been dropped |
|
347 |
+ since the last call to DV1394_GET_STATUS. |
|
348 |
+ */ |
|
349 |
+}; |
|
350 |
+ |
|
351 |
+ |
|
352 |
+#endif /* _DV_1394_H */ |
... | ... |
@@ -53,8 +53,6 @@ static int aiw_init(VideoData *s); |
53 | 53 |
static int aiw_read_picture(VideoData *s, uint8_t *data); |
54 | 54 |
static int aiw_close(VideoData *s); |
55 | 55 |
|
56 |
-const char *v4l_device = "/dev/video"; |
|
57 |
- |
|
58 | 56 |
static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
59 | 57 |
{ |
60 | 58 |
VideoData *s = s1->priv_data; |
... | ... |
@@ -80,9 +78,9 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
80 | 80 |
s->height = height; |
81 | 81 |
s->frame_rate = frame_rate; |
82 | 82 |
|
83 |
- video_fd = open(v4l_device, O_RDWR); |
|
83 |
+ video_fd = open(video_device, O_RDWR); |
|
84 | 84 |
if (video_fd < 0) { |
85 |
- perror(v4l_device); |
|
85 |
+ perror(video_device); |
|
86 | 86 |
goto fail; |
87 | 87 |
} |
88 | 88 |
|
... | ... |
@@ -339,7 +337,7 @@ static int grab_read_close(AVFormatContext *s1) |
339 | 339 |
} |
340 | 340 |
|
341 | 341 |
static AVInputFormat video_grab_device_format = { |
342 |
- "video_grab_device", |
|
342 |
+ "video4linux", |
|
343 | 343 |
"video grab", |
344 | 344 |
sizeof(VideoData), |
345 | 345 |
NULL, |