int stream; /* Current stream. 0 - video, 1 - audio */
int64_t pts; /* Current timestamp */
+ AVStream *vst, *ast;
};
+/*
+ * The trick here is to kludge around well known problem with kernel Ooopsing
+ * when you try to capture PAL on a device node configure for NTSC. That's
+ * why we have to configure the device node for PAL, and then read only NTSC
+ * amount of data.
+ */
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 = dv->format;
+ init.format = DV1394_PAL;
if (ioctl(dv->fd, DV1394_INIT, &init) < 0)
return -1;
static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap)
{
struct dv1394_data *dv = context->priv_data;
- AVStream *vst, *ast;
const char *video_device;
- vst = av_new_stream(context, 0);
- if (!vst)
+ dv->vst = av_new_stream(context, 0);
+ if (!dv->vst)
return -ENOMEM;
- ast = av_new_stream(context, 1);
- if (!ast) {
- av_free(vst);
+ dv->ast = av_new_stream(context, 1);
+ if (!dv->ast) {
+ av_free(dv->vst);
return -ENOMEM;
}
goto failed;
}
- dv->ring = mmap(NULL, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES,
+ dv->ring = mmap(NULL, DV1394_PAL_FRAME_SIZE * DV1394_RING_FRAMES,
PROT_READ, MAP_PRIVATE, dv->fd, 0);
- if (!dv->ring) {
+ if (dv->ring == MAP_FAILED) {
perror("Failed to mmap DV ring buffer");
goto failed;
}
dv->stream = 0;
- vst->codec.codec_type = CODEC_TYPE_VIDEO;
- vst->codec.codec_id = CODEC_ID_DVVIDEO;
- vst->codec.width = dv->width;
- vst->codec.height = dv->height;
- vst->codec.frame_rate = dv->frame_rate;
- vst->codec.frame_rate_base = 1;
- vst->codec.bit_rate = 25000000; /* Consumer DV is 25Mbps */
+ dv->vst->codec.codec_type = CODEC_TYPE_VIDEO;
+ dv->vst->codec.codec_id = CODEC_ID_DVVIDEO;
+ dv->vst->codec.width = dv->width;
+ dv->vst->codec.height = dv->height;
+ dv->vst->codec.frame_rate = dv->frame_rate;
+ dv->vst->codec.frame_rate_base = 1;
+ dv->vst->codec.bit_rate = 25000000; /* Consumer DV is 25Mbps */
- ast->codec.codec_type = CODEC_TYPE_AUDIO;
- ast->codec.codec_id = CODEC_ID_DVAUDIO;
- ast->codec.channels = 2;
- ast->codec.sample_rate= 48000;
+ dv->ast->codec.codec_type = CODEC_TYPE_AUDIO;
+ dv->ast->codec.codec_id = CODEC_ID_DVAUDIO;
+ dv->ast->codec.channels = 2;
+ dv->ast->codec.sample_rate= 48000;
av_set_pts_info(context, 48, 1, 1000000);
failed:
close(dv->fd);
- av_free(vst);
- av_free(ast);
+ av_free(dv->vst);
+ av_free(dv->ast);
return -EIO;
}
static inline int __get_frame(struct dv1394_data *dv, AVPacket *pkt)
{
- char *ptr = dv->ring + (dv->index * dv->frame_size);
+ char *ptr = dv->ring + (dv->index * DV1394_PAL_FRAME_SIZE);
if (dv->stream) {
dv->index = (dv->index + 1) % DV1394_RING_FRAMES;
dv->pts = av_gettime() & ((1LL << 48) - 1);
}
+ dv->format = ((ptr[3] & 0x80) == 0) ? DV1394_NTSC : DV1394_PAL;
+ if (dv->format == DV1394_NTSC) {
+ dv->frame_size = DV1394_NTSC_FRAME_SIZE;
+ dv->vst->codec.height = dv->height = DV1394_NTSC_HEIGHT;
+ dv->vst->codec.frame_rate = dv->frame_rate = 30;
+ } else {
+ dv->frame_size = DV1394_PAL_FRAME_SIZE;
+ dv->vst->codec.height = dv->height = DV1394_PAL_HEIGHT;
+ dv->vst->codec.frame_rate = dv->frame_rate = 25;
+ }
+
av_init_packet(pkt);
pkt->destruct = __destruct_pkt;
pkt->data = ptr;
#ifndef _DV_1394_H
#define _DV_1394_H
-#define DV1394_DEFAULT_CHANNEL 0x63
+#define DV1394_DEFAULT_CHANNEL 63
#define DV1394_DEFAULT_CARD 0
#define DV1394_RING_FRAMES 20
#define DV1394_MAX_FRAMES 32
/* number of *full* isochronous packets per DV frame */
-#define DV1394_NTSC_PACKETS_PER_FRAME 300
-#define DV1394_PAL_PACKETS_PER_FRAME 250
+#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 (576 * DV1394_PAL_PACKETS_PER_FRAME)
+#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME)
/* ioctl() commands */