annotate ffmpeg/libavdevice/dv1394.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Linux DV1394 interface
yading@10 3 * Copyright (c) 2003 Max Krasnyansky <maxk@qualcomm.com>
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 #include "config.h"
yading@10 23 #include <unistd.h>
yading@10 24 #include <fcntl.h>
yading@10 25 #include <errno.h>
yading@10 26 #include <poll.h>
yading@10 27 #include <sys/ioctl.h>
yading@10 28 #include <sys/mman.h>
yading@10 29
yading@10 30 #include "libavutil/log.h"
yading@10 31 #include "libavutil/opt.h"
yading@10 32 #include "avdevice.h"
yading@10 33 #include "libavformat/dv.h"
yading@10 34 #include "dv1394.h"
yading@10 35
yading@10 36 struct dv1394_data {
yading@10 37 AVClass *class;
yading@10 38 int fd;
yading@10 39 int channel;
yading@10 40 int format;
yading@10 41
yading@10 42 uint8_t *ring; /* Ring buffer */
yading@10 43 int index; /* Current frame index */
yading@10 44 int avail; /* Number of frames available for reading */
yading@10 45 int done; /* Number of completed frames */
yading@10 46
yading@10 47 DVDemuxContext* dv_demux; /* Generic DV muxing/demuxing context */
yading@10 48 };
yading@10 49
yading@10 50 /*
yading@10 51 * The trick here is to kludge around well known problem with kernel Ooopsing
yading@10 52 * when you try to capture PAL on a device node configure for NTSC. That's
yading@10 53 * why we have to configure the device node for PAL, and then read only NTSC
yading@10 54 * amount of data.
yading@10 55 */
yading@10 56 static int dv1394_reset(struct dv1394_data *dv)
yading@10 57 {
yading@10 58 struct dv1394_init init;
yading@10 59
yading@10 60 init.channel = dv->channel;
yading@10 61 init.api_version = DV1394_API_VERSION;
yading@10 62 init.n_frames = DV1394_RING_FRAMES;
yading@10 63 init.format = DV1394_PAL;
yading@10 64
yading@10 65 if (ioctl(dv->fd, DV1394_INIT, &init) < 0)
yading@10 66 return -1;
yading@10 67
yading@10 68 dv->avail = dv->done = 0;
yading@10 69 return 0;
yading@10 70 }
yading@10 71
yading@10 72 static int dv1394_start(struct dv1394_data *dv)
yading@10 73 {
yading@10 74 /* Tell DV1394 driver to enable receiver */
yading@10 75 if (ioctl(dv->fd, DV1394_START_RECEIVE, 0) < 0) {
yading@10 76 av_log(NULL, AV_LOG_ERROR, "Failed to start receiver: %s\n", strerror(errno));
yading@10 77 return -1;
yading@10 78 }
yading@10 79 return 0;
yading@10 80 }
yading@10 81
yading@10 82 static int dv1394_read_header(AVFormatContext * context)
yading@10 83 {
yading@10 84 struct dv1394_data *dv = context->priv_data;
yading@10 85
yading@10 86 dv->dv_demux = avpriv_dv_init_demux(context);
yading@10 87 if (!dv->dv_demux)
yading@10 88 goto failed;
yading@10 89
yading@10 90 /* Open and initialize DV1394 device */
yading@10 91 dv->fd = open(context->filename, O_RDONLY);
yading@10 92 if (dv->fd < 0) {
yading@10 93 av_log(context, AV_LOG_ERROR, "Failed to open DV interface: %s\n", strerror(errno));
yading@10 94 goto failed;
yading@10 95 }
yading@10 96
yading@10 97 if (dv1394_reset(dv) < 0) {
yading@10 98 av_log(context, AV_LOG_ERROR, "Failed to initialize DV interface: %s\n", strerror(errno));
yading@10 99 goto failed;
yading@10 100 }
yading@10 101
yading@10 102 dv->ring = mmap(NULL, DV1394_PAL_FRAME_SIZE * DV1394_RING_FRAMES,
yading@10 103 PROT_READ, MAP_PRIVATE, dv->fd, 0);
yading@10 104 if (dv->ring == MAP_FAILED) {
yading@10 105 av_log(context, AV_LOG_ERROR, "Failed to mmap DV ring buffer: %s\n", strerror(errno));
yading@10 106 goto failed;
yading@10 107 }
yading@10 108
yading@10 109 if (dv1394_start(dv) < 0)
yading@10 110 goto failed;
yading@10 111
yading@10 112 return 0;
yading@10 113
yading@10 114 failed:
yading@10 115 close(dv->fd);
yading@10 116 return AVERROR(EIO);
yading@10 117 }
yading@10 118
yading@10 119 static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt)
yading@10 120 {
yading@10 121 struct dv1394_data *dv = context->priv_data;
yading@10 122 int size;
yading@10 123
yading@10 124 size = avpriv_dv_get_packet(dv->dv_demux, pkt);
yading@10 125 if (size > 0)
yading@10 126 return size;
yading@10 127
yading@10 128 if (!dv->avail) {
yading@10 129 struct dv1394_status s;
yading@10 130 struct pollfd p;
yading@10 131
yading@10 132 if (dv->done) {
yading@10 133 /* Request more frames */
yading@10 134 if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) {
yading@10 135 /* This usually means that ring buffer overflowed.
yading@10 136 * We have to reset :(.
yading@10 137 */
yading@10 138
yading@10 139 av_log(context, AV_LOG_ERROR, "DV1394: Ring buffer overflow. Reseting ..\n");
yading@10 140
yading@10 141 dv1394_reset(dv);
yading@10 142 dv1394_start(dv);
yading@10 143 }
yading@10 144 dv->done = 0;
yading@10 145 }
yading@10 146
yading@10 147 /* Wait until more frames are available */
yading@10 148 restart_poll:
yading@10 149 p.fd = dv->fd;
yading@10 150 p.events = POLLIN | POLLERR | POLLHUP;
yading@10 151 if (poll(&p, 1, -1) < 0) {
yading@10 152 if (errno == EAGAIN || errno == EINTR)
yading@10 153 goto restart_poll;
yading@10 154 av_log(context, AV_LOG_ERROR, "Poll failed: %s\n", strerror(errno));
yading@10 155 return AVERROR(EIO);
yading@10 156 }
yading@10 157
yading@10 158 if (ioctl(dv->fd, DV1394_GET_STATUS, &s) < 0) {
yading@10 159 av_log(context, AV_LOG_ERROR, "Failed to get status: %s\n", strerror(errno));
yading@10 160 return AVERROR(EIO);
yading@10 161 }
yading@10 162 av_dlog(context, "DV1394: status\n"
yading@10 163 "\tactive_frame\t%d\n"
yading@10 164 "\tfirst_clear_frame\t%d\n"
yading@10 165 "\tn_clear_frames\t%d\n"
yading@10 166 "\tdropped_frames\t%d\n",
yading@10 167 s.active_frame, s.first_clear_frame,
yading@10 168 s.n_clear_frames, s.dropped_frames);
yading@10 169
yading@10 170 dv->avail = s.n_clear_frames;
yading@10 171 dv->index = s.first_clear_frame;
yading@10 172 dv->done = 0;
yading@10 173
yading@10 174 if (s.dropped_frames) {
yading@10 175 av_log(context, AV_LOG_ERROR, "DV1394: Frame drop detected (%d). Reseting ..\n",
yading@10 176 s.dropped_frames);
yading@10 177
yading@10 178 dv1394_reset(dv);
yading@10 179 dv1394_start(dv);
yading@10 180 }
yading@10 181 }
yading@10 182
yading@10 183 av_dlog(context, "index %d, avail %d, done %d\n", dv->index, dv->avail,
yading@10 184 dv->done);
yading@10 185
yading@10 186 size = avpriv_dv_produce_packet(dv->dv_demux, pkt,
yading@10 187 dv->ring + (dv->index * DV1394_PAL_FRAME_SIZE),
yading@10 188 DV1394_PAL_FRAME_SIZE, -1);
yading@10 189 dv->index = (dv->index + 1) % DV1394_RING_FRAMES;
yading@10 190 dv->done++; dv->avail--;
yading@10 191
yading@10 192 return size;
yading@10 193 }
yading@10 194
yading@10 195 static int dv1394_close(AVFormatContext * context)
yading@10 196 {
yading@10 197 struct dv1394_data *dv = context->priv_data;
yading@10 198
yading@10 199 /* Shutdown DV1394 receiver */
yading@10 200 if (ioctl(dv->fd, DV1394_SHUTDOWN, 0) < 0)
yading@10 201 av_log(context, AV_LOG_ERROR, "Failed to shutdown DV1394: %s\n", strerror(errno));
yading@10 202
yading@10 203 /* Unmap ring buffer */
yading@10 204 if (munmap(dv->ring, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES) < 0)
yading@10 205 av_log(context, AV_LOG_ERROR, "Failed to munmap DV1394 ring buffer: %s\n", strerror(errno));
yading@10 206
yading@10 207 close(dv->fd);
yading@10 208 av_free(dv->dv_demux);
yading@10 209
yading@10 210 return 0;
yading@10 211 }
yading@10 212
yading@10 213 static const AVOption options[] = {
yading@10 214 { "standard", "", offsetof(struct dv1394_data, format), AV_OPT_TYPE_INT, {.i64 = DV1394_NTSC}, DV1394_NTSC, DV1394_PAL, AV_OPT_FLAG_DECODING_PARAM, "standard" },
yading@10 215 { "PAL", "", 0, AV_OPT_TYPE_CONST, {.i64 = DV1394_PAL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" },
yading@10 216 { "NTSC", "", 0, AV_OPT_TYPE_CONST, {.i64 = DV1394_NTSC}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" },
yading@10 217 { "channel", "", offsetof(struct dv1394_data, channel), AV_OPT_TYPE_INT, {.i64 = DV1394_DEFAULT_CHANNEL}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
yading@10 218 { NULL },
yading@10 219 };
yading@10 220
yading@10 221 static const AVClass dv1394_class = {
yading@10 222 .class_name = "DV1394 indev",
yading@10 223 .item_name = av_default_item_name,
yading@10 224 .option = options,
yading@10 225 .version = LIBAVUTIL_VERSION_INT,
yading@10 226 };
yading@10 227
yading@10 228 AVInputFormat ff_dv1394_demuxer = {
yading@10 229 .name = "dv1394",
yading@10 230 .long_name = NULL_IF_CONFIG_SMALL("DV1394 A/V grab"),
yading@10 231 .priv_data_size = sizeof(struct dv1394_data),
yading@10 232 .read_header = dv1394_read_header,
yading@10 233 .read_packet = dv1394_read_packet,
yading@10 234 .read_close = dv1394_close,
yading@10 235 .flags = AVFMT_NOFILE,
yading@10 236 .priv_class = &dv1394_class,
yading@10 237 };