diff --git a/libavformat/dv1394.c b/libavformat/dv1394.c index 0e373a311d..8cdb924b33 100644 --- a/libavformat/dv1394.c +++ b/libavformat/dv1394.c @@ -47,8 +47,15 @@ struct dv1394_data { 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; @@ -56,7 +63,7 @@ static int dv1394_reset(struct dv1394_data *dv) 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; @@ -79,15 +86,14 @@ static int dv1394_start(struct dv1394_data *dv) 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; } @@ -127,27 +133,27 @@ static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap 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); @@ -158,8 +164,8 @@ static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap failed: close(dv->fd); - av_free(vst); - av_free(ast); + av_free(dv->vst); + av_free(dv->ast); return -EIO; } @@ -171,7 +177,7 @@ static void __destruct_pkt(struct AVPacket *pkt) 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; @@ -180,6 +186,17 @@ static inline int __get_frame(struct dv1394_data *dv, AVPacket *pkt) 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; diff --git a/libavformat/dv1394.h b/libavformat/dv1394.h index 6fcbdb0179..8c0422a5d9 100644 --- a/libavformat/dv1394.h +++ b/libavformat/dv1394.h @@ -26,7 +26,7 @@ #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 @@ -199,12 +199,12 @@ #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 */