Mercurial > libavformat.hg
annotate dv1394.c @ 1960:c0289552590f libavformat
Change the vhook code to send real timestamps to the filters instead of the
current time of day, which is useless, and which the filters could just as
easily query for themselves.
patch by Bobby Bingham, uhmmmm gmail com
author | diego |
---|---|
date | Thu, 29 Mar 2007 05:24:35 +0000 |
parents | 62792a60f740 |
children | b21c2af60bc9 |
rev | line source |
---|---|
27 | 1 /* |
2 * Linux DV1394 interface | |
3 * Copyright (c) 2003 Max Krasnyansky <maxk@qualcomm.com> | |
4 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
27 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
27 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
27 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
887
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
27 | 20 */ |
21 | |
22 #include <unistd.h> | |
23 #include <fcntl.h> | |
53
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
24 #include <errno.h> |
27 | 25 #include <sys/ioctl.h> |
26 #include <sys/mman.h> | |
27 #include <sys/poll.h> | |
28 #include <sys/time.h> | |
29 #include <time.h> | |
30 | |
31 #include "avformat.h" | |
32 | |
33 #undef DV1394_DEBUG | |
34 | |
35 #include "dv1394.h" | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
36 #include "dv.h" |
27 | 37 |
38 struct dv1394_data { | |
39 int fd; | |
40 int channel; | |
38 | 41 int format; |
27 | 42 |
1739 | 43 uint8_t *ring; /* Ring buffer */ |
27 | 44 int index; /* Current frame index */ |
45 int avail; /* Number of frames available for reading */ | |
46 int done; /* Number of completed frames */ | |
38 | 47 |
296
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
48 DVDemuxContext* dv_demux; /* Generic DV muxing/demuxing context */ |
27 | 49 }; |
50 | |
885 | 51 /* |
185
d98ed04d62a6
patch for DV capturing by Dan Dennedy <dan at dennedy dot org>
romansh
parents:
159
diff
changeset
|
52 * The trick here is to kludge around well known problem with kernel Ooopsing |
885 | 53 * when you try to capture PAL on a device node configure for NTSC. That's |
185
d98ed04d62a6
patch for DV capturing by Dan Dennedy <dan at dennedy dot org>
romansh
parents:
159
diff
changeset
|
54 * why we have to configure the device node for PAL, and then read only NTSC |
d98ed04d62a6
patch for DV capturing by Dan Dennedy <dan at dennedy dot org>
romansh
parents:
159
diff
changeset
|
55 * amount of data. |
d98ed04d62a6
patch for DV capturing by Dan Dennedy <dan at dennedy dot org>
romansh
parents:
159
diff
changeset
|
56 */ |
27 | 57 static int dv1394_reset(struct dv1394_data *dv) |
58 { | |
59 struct dv1394_init init; | |
60 | |
38 | 61 init.channel = dv->channel; |
27 | 62 init.api_version = DV1394_API_VERSION; |
38 | 63 init.n_frames = DV1394_RING_FRAMES; |
185
d98ed04d62a6
patch for DV capturing by Dan Dennedy <dan at dennedy dot org>
romansh
parents:
159
diff
changeset
|
64 init.format = DV1394_PAL; |
27 | 65 |
66 if (ioctl(dv->fd, DV1394_INIT, &init) < 0) | |
67 return -1; | |
68 | |
53
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
69 dv->avail = dv->done = 0; |
27 | 70 return 0; |
71 } | |
72 | |
73 static int dv1394_start(struct dv1394_data *dv) | |
74 { | |
75 /* Tell DV1394 driver to enable receiver */ | |
76 if (ioctl(dv->fd, DV1394_START_RECEIVE, 0) < 0) { | |
77 perror("Failed to start receiver"); | |
78 return -1; | |
79 } | |
80 return 0; | |
81 } | |
82 | |
83 static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap) | |
84 { | |
85 struct dv1394_data *dv = context->priv_data; | |
86 | |
296
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
87 dv->dv_demux = dv_init_demux(context); |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
88 if (!dv->dv_demux) |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
89 goto failed; |
27 | 90 |
159
7d698c3213a0
tv standard selection support for dv1394 and grab (v4l)
al3x
parents:
156
diff
changeset
|
91 if (ap->standard && !strcasecmp(ap->standard, "pal")) |
887 | 92 dv->format = DV1394_PAL; |
159
7d698c3213a0
tv standard selection support for dv1394 and grab (v4l)
al3x
parents:
156
diff
changeset
|
93 else |
887 | 94 dv->format = DV1394_NTSC; |
31
36dd902f98d2
dv1394 channel selection by Max Krasnyansky - modified channel number to be in base 10 by default
bellard
parents:
30
diff
changeset
|
95 |
36dd902f98d2
dv1394 channel selection by Max Krasnyansky - modified channel number to be in base 10 by default
bellard
parents:
30
diff
changeset
|
96 if (ap->channel) |
36dd902f98d2
dv1394 channel selection by Max Krasnyansky - modified channel number to be in base 10 by default
bellard
parents:
30
diff
changeset
|
97 dv->channel = ap->channel; |
36dd902f98d2
dv1394 channel selection by Max Krasnyansky - modified channel number to be in base 10 by default
bellard
parents:
30
diff
changeset
|
98 else |
36dd902f98d2
dv1394 channel selection by Max Krasnyansky - modified channel number to be in base 10 by default
bellard
parents:
30
diff
changeset
|
99 dv->channel = DV1394_DEFAULT_CHANNEL; |
27 | 100 |
101 /* Open and initialize DV1394 device */ | |
1795
62792a60f740
implement new grabbing interface, as described here:
gpoirier
parents:
1739
diff
changeset
|
102 dv->fd = open(context->filename, O_RDONLY); |
27 | 103 if (dv->fd < 0) { |
104 perror("Failed to open DV interface"); | |
105 goto failed; | |
106 } | |
107 | |
108 if (dv1394_reset(dv) < 0) { | |
109 perror("Failed to initialize DV interface"); | |
110 goto failed; | |
111 } | |
112 | |
185
d98ed04d62a6
patch for DV capturing by Dan Dennedy <dan at dennedy dot org>
romansh
parents:
159
diff
changeset
|
113 dv->ring = mmap(NULL, DV1394_PAL_FRAME_SIZE * DV1394_RING_FRAMES, |
27 | 114 PROT_READ, MAP_PRIVATE, dv->fd, 0); |
185
d98ed04d62a6
patch for DV capturing by Dan Dennedy <dan at dennedy dot org>
romansh
parents:
159
diff
changeset
|
115 if (dv->ring == MAP_FAILED) { |
27 | 116 perror("Failed to mmap DV ring buffer"); |
117 goto failed; | |
118 } | |
119 | |
120 if (dv1394_start(dv) < 0) | |
121 goto failed; | |
122 | |
123 return 0; | |
124 | |
125 failed: | |
126 close(dv->fd); | |
482 | 127 return AVERROR_IO; |
27 | 128 } |
129 | |
38 | 130 static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt) |
27 | 131 { |
132 struct dv1394_data *dv = context->priv_data; | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
133 int size; |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
134 |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
135 size = dv_get_packet(dv->dv_demux, pkt); |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
136 if (size > 0) |
392 | 137 return size; |
27 | 138 |
139 if (!dv->avail) { | |
140 struct dv1394_status s; | |
141 struct pollfd p; | |
53
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
142 |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
143 if (dv->done) { |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
144 /* Request more frames */ |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
145 if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) { |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
146 /* This usually means that ring buffer overflowed. |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
147 * We have to reset :(. |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
148 */ |
885 | 149 |
370
845f9de2c883
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
296
diff
changeset
|
150 av_log(context, AV_LOG_ERROR, "DV1394: Ring buffer overflow. Reseting ..\n"); |
885 | 151 |
53
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
152 dv1394_reset(dv); |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
153 dv1394_start(dv); |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
154 } |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
155 dv->done = 0; |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
156 } |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
157 |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
158 /* Wait until more frames are available */ |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
159 restart_poll: |
27 | 160 p.fd = dv->fd; |
161 p.events = POLLIN | POLLERR | POLLHUP; | |
162 if (poll(&p, 1, -1) < 0) { | |
53
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
163 if (errno == EAGAIN || errno == EINTR) |
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
164 goto restart_poll; |
27 | 165 perror("Poll failed"); |
482 | 166 return AVERROR_IO; |
27 | 167 } |
168 | |
169 if (ioctl(dv->fd, DV1394_GET_STATUS, &s) < 0) { | |
170 perror("Failed to get status"); | |
482 | 171 return AVERROR_IO; |
27 | 172 } |
173 #ifdef DV1394_DEBUG | |
1002
56db80b1131e
Use AV_LOG_DEBUG loglevel instead of AV_LOG_ERROR where appropriate.
diego
parents:
1001
diff
changeset
|
174 av_log(context, AV_LOG_DEBUG, "DV1394: status\n" |
27 | 175 "\tactive_frame\t%d\n" |
176 "\tfirst_clear_frame\t%d\n" | |
177 "\tn_clear_frames\t%d\n" | |
178 "\tdropped_frames\t%d\n", | |
179 s.active_frame, s.first_clear_frame, | |
180 s.n_clear_frames, s.dropped_frames); | |
181 #endif | |
182 | |
183 dv->avail = s.n_clear_frames; | |
184 dv->index = s.first_clear_frame; | |
53
fb671d87824e
zero copy packet handling for DV1394 by Max Krasnyansky
bellard
parents:
38
diff
changeset
|
185 dv->done = 0; |
27 | 186 |
187 if (s.dropped_frames) { | |
370
845f9de2c883
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
296
diff
changeset
|
188 av_log(context, AV_LOG_ERROR, "DV1394: Frame drop detected (%d). Reseting ..\n", |
27 | 189 s.dropped_frames); |
190 | |
191 dv1394_reset(dv); | |
192 dv1394_start(dv); | |
193 } | |
194 } | |
195 | |
196 #ifdef DV1394_DEBUG | |
1002
56db80b1131e
Use AV_LOG_DEBUG loglevel instead of AV_LOG_ERROR where appropriate.
diego
parents:
1001
diff
changeset
|
197 av_log(context, AV_LOG_DEBUG, "index %d, avail %d, done %d\n", dv->index, dv->avail, |
27 | 198 dv->done); |
199 #endif | |
200 | |
885 | 201 size = dv_produce_packet(dv->dv_demux, pkt, |
202 dv->ring + (dv->index * DV1394_PAL_FRAME_SIZE), | |
887 | 203 DV1394_PAL_FRAME_SIZE); |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
204 dv->index = (dv->index + 1) % DV1394_RING_FRAMES; |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
205 dv->done++; dv->avail--; |
885 | 206 |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
207 return size; |
27 | 208 } |
209 | |
210 static int dv1394_close(AVFormatContext * context) | |
211 { | |
212 struct dv1394_data *dv = context->priv_data; | |
213 | |
214 /* Shutdown DV1394 receiver */ | |
215 if (ioctl(dv->fd, DV1394_SHUTDOWN, 0) < 0) | |
216 perror("Failed to shutdown DV1394"); | |
217 | |
218 /* Unmap ring buffer */ | |
219 if (munmap(dv->ring, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES) < 0) | |
220 perror("Failed to munmap DV1394 ring buffer"); | |
221 | |
222 close(dv->fd); | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
185
diff
changeset
|
223 av_free(dv->dv_demux); |
27 | 224 |
225 return 0; | |
226 } | |
227 | |
1169 | 228 AVInputFormat dv1394_demuxer = { |
27 | 229 .name = "dv1394", |
230 .long_name = "dv1394 A/V grab", | |
231 .priv_data_size = sizeof(struct dv1394_data), | |
232 .read_header = dv1394_read_header, | |
233 .read_packet = dv1394_read_packet, | |
234 .read_close = dv1394_close, | |
235 .flags = AVFMT_NOFILE | |
236 }; |