Commit | Line | Data |
---|---|---|
f02be79d RS |
1 | /* |
2 | * IIDC1394 grab interface (uses libdc1394 and libraw1394) | |
3 | * Copyright (c) 2004 Roman Shaposhnik | |
4 | * | |
b78e7197 DB |
5 | * This file is part of FFmpeg. |
6 | * | |
7 | * FFmpeg is free software; you can redistribute it and/or | |
f02be79d RS |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either | |
b78e7197 | 10 | * version 2.1 of the License, or (at your option) any later version. |
f02be79d | 11 | * |
b78e7197 | 12 | * FFmpeg is distributed in the hope that it will be useful, |
f02be79d RS |
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 | |
b78e7197 | 18 | * License along with FFmpeg; if not, write to the Free Software |
5509bffa | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
f02be79d RS |
20 | */ |
21 | ||
22 | #include "avformat.h" | |
23 | ||
24 | #include <libraw1394/raw1394.h> | |
25 | #include <libdc1394/dc1394_control.h> | |
26 | ||
27 | #undef free | |
28 | ||
29 | typedef struct dc1394_data { | |
30 | raw1394handle_t handle; | |
31 | dc1394_cameracapture camera; | |
32 | int current_frame; | |
33 | int fps; | |
34 | ||
35 | AVPacket packet; | |
36 | } dc1394_data; | |
37 | ||
38 | struct dc1394_frame_format { | |
39 | int width; | |
40 | int height; | |
41 | enum PixelFormat pix_fmt; | |
42 | int frame_size_id; | |
43 | } dc1394_frame_formats[] = { | |
44 | { 320, 240, PIX_FMT_UYVY422, MODE_320x240_YUV422 }, | |
71e445fc | 45 | { 640, 480, PIX_FMT_UYYVYY411, MODE_640x480_YUV411 }, |
f02be79d RS |
46 | { 640, 480, PIX_FMT_UYVY422, MODE_640x480_YUV422 }, |
47 | { 0, 0, 0, MODE_320x240_YUV422 } /* default -- gotta be the last one */ | |
48 | }; | |
49 | ||
50 | struct dc1394_frame_rate { | |
51 | int frame_rate; | |
52 | int frame_rate_id; | |
53 | } dc1394_frame_rates[] = { | |
54 | { 1875, FRAMERATE_1_875 }, | |
55 | { 3750, FRAMERATE_3_75 }, | |
56 | { 7500, FRAMERATE_7_5 }, | |
57 | { 15000, FRAMERATE_15 }, | |
58 | { 30000, FRAMERATE_30 }, | |
59 | { 60000, FRAMERATE_60 }, | |
60 | { 0, FRAMERATE_30 } /* default -- gotta be the last one */ | |
61 | }; | |
62 | ||
63 | static int dc1394_read_header(AVFormatContext *c, AVFormatParameters * ap) | |
64 | { | |
65 | dc1394_data* dc1394 = c->priv_data; | |
66 | AVStream* vst; | |
67 | nodeid_t* camera_nodes; | |
68 | int res; | |
69 | struct dc1394_frame_format *fmt; | |
70 | struct dc1394_frame_rate *fps; | |
71 | ||
72 | for (fmt = dc1394_frame_formats; fmt->width; fmt++) | |
73 | if (fmt->pix_fmt == ap->pix_fmt && fmt->width == ap->width && fmt->height == ap->height) | |
bb270c08 | 74 | break; |
115329f1 | 75 | |
f02be79d | 76 | for (fps = dc1394_frame_rates; fps->frame_rate; fps++) |
c0df9d75 | 77 | if (fps->frame_rate == av_rescale(1000, ap->time_base.den, ap->time_base.num)) |
bb270c08 | 78 | break; |
115329f1 | 79 | |
f02be79d RS |
80 | /* create a video stream */ |
81 | vst = av_new_stream(c, 0); | |
82 | if (!vst) | |
bb270c08 | 83 | return -1; |
f02be79d | 84 | av_set_pts_info(vst, 64, 1, 1000); |
9f747cc3 SH |
85 | vst->codec->codec_type = CODEC_TYPE_VIDEO; |
86 | vst->codec->codec_id = CODEC_ID_RAWVIDEO; | |
87 | vst->codec->time_base.den = fps->frame_rate; | |
88 | vst->codec->time_base.num = 1000; | |
89 | vst->codec->width = fmt->width; | |
90 | vst->codec->height = fmt->height; | |
91 | vst->codec->pix_fmt = fmt->pix_fmt; | |
f02be79d RS |
92 | |
93 | /* packet init */ | |
94 | av_init_packet(&dc1394->packet); | |
95 | dc1394->packet.size = avpicture_get_size(fmt->pix_fmt, fmt->width, fmt->height); | |
96 | dc1394->packet.stream_index = vst->index; | |
97 | dc1394->packet.flags |= PKT_FLAG_KEY; | |
115329f1 | 98 | |
f02be79d RS |
99 | dc1394->current_frame = 0; |
100 | dc1394->fps = fps->frame_rate; | |
101 | ||
9f747cc3 | 102 | vst->codec->bit_rate = av_rescale(dc1394->packet.size * 8, fps->frame_rate, 1000); |
115329f1 | 103 | |
f02be79d RS |
104 | /* Now lets prep the hardware */ |
105 | dc1394->handle = dc1394_create_handle(0); /* FIXME: gotta have ap->port */ | |
106 | if (!dc1394->handle) { | |
bb270c08 | 107 | av_log(c, AV_LOG_ERROR, "Can't acquire dc1394 handle on port %d\n", 0 /* ap->port */); |
f02be79d RS |
108 | goto out; |
109 | } | |
110 | camera_nodes = dc1394_get_camera_nodes(dc1394->handle, &res, 1); | |
111 | if (!camera_nodes || camera_nodes[ap->channel] == DC1394_NO_CAMERA) { | |
112 | av_log(c, AV_LOG_ERROR, "There's no IIDC camera on the channel %d\n", ap->channel); | |
115329f1 | 113 | goto out_handle; |
f02be79d | 114 | } |
115329f1 | 115 | res = dc1394_dma_setup_capture(dc1394->handle, camera_nodes[ap->channel], |
bb270c08 DB |
116 | 0, |
117 | FORMAT_VGA_NONCOMPRESSED, | |
118 | fmt->frame_size_id, | |
119 | SPEED_400, | |
120 | fps->frame_rate_id, 8, 1, | |
cc58300e | 121 | c->filename, |
bb270c08 | 122 | &dc1394->camera); |
f02be79d RS |
123 | dc1394_free_camera_nodes(camera_nodes); |
124 | if (res != DC1394_SUCCESS) { | |
125 | av_log(c, AV_LOG_ERROR, "Can't prepare camera for the DMA capture\n"); | |
bb270c08 | 126 | goto out_handle; |
f02be79d RS |
127 | } |
128 | ||
129 | res = dc1394_start_iso_transmission(dc1394->handle, dc1394->camera.node); | |
130 | if (res != DC1394_SUCCESS) { | |
131 | av_log(c, AV_LOG_ERROR, "Can't start isochronous transmission\n"); | |
bb270c08 | 132 | goto out_handle_dma; |
f02be79d | 133 | } |
115329f1 | 134 | |
f02be79d RS |
135 | return 0; |
136 | ||
137 | out_handle_dma: | |
138 | dc1394_dma_unlisten(dc1394->handle, &dc1394->camera); | |
139 | dc1394_dma_release_camera(dc1394->handle, &dc1394->camera); | |
140 | out_handle: | |
141 | dc1394_destroy_handle(dc1394->handle); | |
142 | out: | |
143 | return -1; | |
144 | } | |
145 | ||
146 | static int dc1394_read_packet(AVFormatContext *c, AVPacket *pkt) | |
147 | { | |
148 | struct dc1394_data *dc1394 = c->priv_data; | |
149 | int res; | |
115329f1 | 150 | |
f02be79d RS |
151 | /* discard stale frame */ |
152 | if (dc1394->current_frame++) { | |
bb270c08 | 153 | if (dc1394_dma_done_with_buffer(&dc1394->camera) != DC1394_SUCCESS) |
f02be79d RS |
154 | av_log(c, AV_LOG_ERROR, "failed to release %d frame\n", dc1394->current_frame); |
155 | } | |
115329f1 | 156 | |
f02be79d RS |
157 | res = dc1394_dma_single_capture(&dc1394->camera); |
158 | ||
159 | if (res == DC1394_SUCCESS) { | |
115329f1 DB |
160 | dc1394->packet.data = (uint8_t *)(dc1394->camera.capture_buffer); |
161 | dc1394->packet.pts = (dc1394->current_frame * 1000000) / dc1394->fps; | |
bb270c08 | 162 | res = dc1394->packet.size; |
f02be79d RS |
163 | } else { |
164 | av_log(c, AV_LOG_ERROR, "DMA capture failed\n"); | |
165 | dc1394->packet.data = NULL; | |
115329f1 | 166 | res = -1; |
f02be79d | 167 | } |
115329f1 | 168 | |
f02be79d RS |
169 | *pkt = dc1394->packet; |
170 | return res; | |
171 | } | |
172 | ||
173 | static int dc1394_close(AVFormatContext * context) | |
174 | { | |
175 | struct dc1394_data *dc1394 = context->priv_data; | |
176 | ||
177 | dc1394_stop_iso_transmission(dc1394->handle, dc1394->camera.node); | |
178 | dc1394_dma_unlisten(dc1394->handle, &dc1394->camera); | |
179 | dc1394_dma_release_camera(dc1394->handle, &dc1394->camera); | |
180 | dc1394_destroy_handle(dc1394->handle); | |
115329f1 | 181 | |
f02be79d RS |
182 | return 0; |
183 | } | |
184 | ||
f7b8bffe | 185 | AVInputFormat libdc1394_demuxer = { |
5fdb9cc5 | 186 | .name = "libdc1394", |
f02be79d RS |
187 | .long_name = "dc1394 A/V grab", |
188 | .priv_data_size = sizeof(struct dc1394_data), | |
189 | .read_header = dc1394_read_header, | |
190 | .read_packet = dc1394_read_packet, | |
191 | .read_close = dc1394_close, | |
192 | .flags = AVFMT_NOFILE | |
193 | }; |