Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * Copyright (c) 2012 Georg Lippitsch |
||
3 | * |
||
4 | * This file is part of FFmpeg. |
||
5 | * |
||
6 | * FFmpeg is free software; you can redistribute it and/or |
||
7 | * modify it under the terms of the GNU Lesser General Public |
||
8 | * License as published by the Free Software Foundation; either |
||
9 | * version 2.1 of the License, or (at your option) any later version. |
||
10 | * |
||
11 | * FFmpeg is distributed in the hope that it will be useful, |
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
14 | * Lesser General Public License for more details. |
||
15 | * |
||
16 | * You should have received a copy of the GNU Lesser General Public |
||
17 | * License along with FFmpeg; if not, write to the Free Software |
||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||
19 | */ |
||
20 | |||
21 | /** |
||
22 | * @file |
||
23 | * libiec61883 interface |
||
24 | */ |
||
25 | |||
26 | #include |
||
27 | #include |
||
28 | #include |
||
29 | #include |
||
30 | #include |
||
31 | #include "libavformat/dv.h" |
||
32 | #include "libavformat/mpegts.h" |
||
33 | #include "libavutil/opt.h" |
||
34 | #include "avdevice.h" |
||
35 | |||
36 | #define THREADS HAVE_PTHREADS |
||
37 | |||
38 | #if THREADS |
||
39 | #include |
||
40 | #endif |
||
41 | |||
42 | #define MOTDCT_SPEC_ID 0x00005068 |
||
43 | #define IEC61883_AUTO 0 |
||
44 | #define IEC61883_DV 1 |
||
45 | #define IEC61883_HDV 2 |
||
46 | |||
47 | /** |
||
48 | * For DV, one packet corresponds exactly to one frame. |
||
49 | * For HDV, these are MPEG2 transport stream packets. |
||
50 | * The queue is implemented as linked list. |
||
51 | */ |
||
52 | typedef struct DVPacket { |
||
53 | uint8_t *buf; ///< actual buffer data |
||
54 | int len; ///< size of buffer allocated |
||
55 | struct DVPacket *next; ///< next DVPacket |
||
56 | } DVPacket; |
||
57 | |||
58 | struct iec61883_data { |
||
59 | AVClass *class; |
||
60 | raw1394handle_t raw1394; ///< handle for libraw1394 |
||
61 | iec61883_dv_fb_t iec61883_dv; ///< handle for libiec61883 when used with DV |
||
62 | iec61883_mpeg2_t iec61883_mpeg2; ///< handle for libiec61883 when used with HDV |
||
63 | |||
64 | DVDemuxContext *dv_demux; ///< generic DV muxing/demuxing context |
||
65 | MpegTSContext *mpeg_demux; ///< generic HDV muxing/demuxing context |
||
66 | |||
67 | DVPacket *queue_first; ///< first element of packet queue |
||
68 | DVPacket *queue_last; ///< last element of packet queue |
||
69 | |||
70 | char *device_guid; ///< to select one of multiple DV devices |
||
71 | |||
72 | int packets; ///< Number of packets queued |
||
73 | int max_packets; ///< Max. number of packets in queue |
||
74 | |||
75 | int bandwidth; ///< returned by libiec61883 |
||
76 | int channel; ///< returned by libiec61883 |
||
77 | int input_port; ///< returned by libiec61883 |
||
78 | int type; ///< Stream type, to distinguish DV/HDV |
||
79 | int node; ///< returned by libiec61883 |
||
80 | int output_port; ///< returned by libiec61883 |
||
81 | int thread_loop; ///< Condition for thread while-loop |
||
82 | int receiving; ///< True as soon data from device available |
||
83 | int receive_error; ///< Set in receive task in case of error |
||
84 | int eof; ///< True as soon as no more data available |
||
85 | |||
86 | struct pollfd raw1394_poll; ///< to poll for new data from libraw1394 |
||
87 | |||
88 | /** Parse function for DV/HDV differs, so this is set before packets arrive */ |
||
89 | int (*parse_queue)(struct iec61883_data *dv, AVPacket *pkt); |
||
90 | |||
91 | #if THREADS |
||
92 | pthread_t receive_task_thread; |
||
93 | pthread_mutex_t mutex; |
||
94 | pthread_cond_t cond; |
||
95 | #endif |
||
96 | }; |
||
97 | |||
98 | static int iec61883_callback(unsigned char *data, int length, |
||
99 | int complete, void *callback_data) |
||
100 | { |
||
101 | struct iec61883_data *dv = callback_data; |
||
102 | DVPacket *packet; |
||
103 | int ret; |
||
104 | |||
105 | #ifdef THREADS |
||
106 | pthread_mutex_lock(&dv->mutex); |
||
107 | #endif |
||
108 | |||
109 | if (dv->packets >= dv->max_packets) { |
||
110 | av_log(NULL, AV_LOG_ERROR, "DV packet queue overrun, dropping.\n"); |
||
111 | ret = 0; |
||
112 | goto exit; |
||
113 | } |
||
114 | |||
115 | packet = av_mallocz(sizeof(*packet)); |
||
116 | if (!packet) { |
||
117 | ret = -1; |
||
118 | goto exit; |
||
119 | } |
||
120 | |||
121 | packet->buf = av_malloc(length); |
||
122 | if (!packet->buf) { |
||
123 | ret = -1; |
||
124 | goto exit; |
||
125 | } |
||
126 | packet->len = length; |
||
127 | |||
128 | memcpy(packet->buf, data, length); |
||
129 | |||
130 | if (dv->queue_first) { |
||
131 | dv->queue_last->next = packet; |
||
132 | dv->queue_last = packet; |
||
133 | } else { |
||
134 | dv->queue_first = packet; |
||
135 | dv->queue_last = packet; |
||
136 | } |
||
137 | dv->packets++; |
||
138 | |||
139 | ret = 0; |
||
140 | |||
141 | exit: |
||
142 | #ifdef THREADS |
||
143 | pthread_cond_broadcast(&dv->cond); |
||
144 | pthread_mutex_unlock(&dv->mutex); |
||
145 | #endif |
||
146 | return ret; |
||
147 | } |
||
148 | |||
149 | static void *iec61883_receive_task(void *opaque) |
||
150 | { |
||
151 | struct iec61883_data *dv = (struct iec61883_data *)opaque; |
||
152 | int result; |
||
153 | |||
154 | #ifdef THREADS |
||
155 | while (dv->thread_loop) |
||
156 | #endif |
||
157 | { |
||
158 | while ((result = poll(&dv->raw1394_poll, 1, 200)) < 0) { |
||
159 | if (!(errno == EAGAIN || errno == EINTR)) { |
||
160 | av_log(NULL, AV_LOG_ERROR, "Raw1394 poll error occurred.\n"); |
||
161 | dv->receive_error = AVERROR(EIO); |
||
162 | return NULL; |
||
163 | } |
||
164 | } |
||
165 | if (result > 0 && ((dv->raw1394_poll.revents & POLLIN) |
||
166 | || (dv->raw1394_poll.revents & POLLPRI))) { |
||
167 | dv->receiving = 1; |
||
168 | raw1394_loop_iterate(dv->raw1394); |
||
169 | } else if (dv->receiving) { |
||
170 | av_log(NULL, AV_LOG_ERROR, "No more input data available\n"); |
||
171 | #ifdef THREADS |
||
172 | pthread_mutex_lock(&dv->mutex); |
||
173 | dv->eof = 1; |
||
174 | pthread_cond_broadcast(&dv->cond); |
||
175 | pthread_mutex_unlock(&dv->mutex); |
||
176 | #else |
||
177 | dv->eof = 1; |
||
178 | #endif |
||
179 | return NULL; |
||
180 | } |
||
181 | } |
||
182 | |||
183 | return NULL; |
||
184 | } |
||
185 | |||
186 | static int iec61883_parse_queue_dv(struct iec61883_data *dv, AVPacket *pkt) |
||
187 | { |
||
188 | DVPacket *packet; |
||
189 | int size; |
||
190 | |||
191 | size = avpriv_dv_get_packet(dv->dv_demux, pkt); |
||
192 | if (size > 0) |
||
193 | return size; |
||
194 | |||
195 | packet = dv->queue_first; |
||
196 | if (!packet) |
||
197 | return -1; |
||
198 | |||
199 | size = avpriv_dv_produce_packet(dv->dv_demux, pkt, |
||
200 | packet->buf, packet->len, -1); |
||
201 | pkt->destruct = av_destruct_packet; |
||
202 | dv->queue_first = packet->next; |
||
203 | av_free(packet); |
||
204 | dv->packets--; |
||
205 | |||
206 | if (size > 0) |
||
207 | return size; |
||
208 | |||
209 | return -1; |
||
210 | } |
||
211 | |||
212 | static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt) |
||
213 | { |
||
214 | DVPacket *packet; |
||
215 | int size; |
||
216 | |||
217 | while (dv->queue_first) { |
||
218 | packet = dv->queue_first; |
||
219 | size = ff_mpegts_parse_packet(dv->mpeg_demux, pkt, packet->buf, |
||
220 | packet->len); |
||
221 | dv->queue_first = packet->next; |
||
222 | av_free(packet->buf); |
||
223 | av_free(packet); |
||
224 | dv->packets--; |
||
225 | |||
226 | if (size > 0) |
||
227 | return size; |
||
228 | } |
||
229 | |||
230 | return -1; |
||
231 | } |
||
232 | |||
233 | static int iec61883_read_header(AVFormatContext *context) |
||
234 | { |
||
235 | struct iec61883_data *dv = context->priv_data; |
||
236 | struct raw1394_portinfo pinf[16]; |
||
237 | rom1394_directory rom_dir; |
||
238 | char *endptr; |
||
239 | int inport; |
||
240 | int nb_ports; |
||
241 | int port = -1; |
||
242 | int response; |
||
243 | int i, j = 0; |
||
244 | uint64_t guid = 0; |
||
245 | |||
246 | dv->input_port = -1; |
||
247 | dv->output_port = -1; |
||
248 | dv->channel = -1; |
||
249 | |||
250 | dv->raw1394 = raw1394_new_handle(); |
||
251 | |||
252 | if (!dv->raw1394) { |
||
253 | av_log(context, AV_LOG_ERROR, "Failed to open IEEE1394 interface.\n"); |
||
254 | return AVERROR(EIO); |
||
255 | } |
||
256 | |||
257 | if ((nb_ports = raw1394_get_port_info(dv->raw1394, pinf, 16)) < 0) { |
||
258 | av_log(context, AV_LOG_ERROR, "Failed to get number of IEEE1394 ports.\n"); |
||
259 | goto fail; |
||
260 | } |
||
261 | |||
262 | inport = strtol(context->filename, &endptr, 10); |
||
263 | if (endptr != context->filename && *endptr == '\0') { |
||
264 | av_log(context, AV_LOG_INFO, "Selecting IEEE1394 port: %d\n", inport); |
||
265 | j = inport; |
||
266 | nb_ports = inport + 1; |
||
267 | } else if (strcmp(context->filename, "auto")) { |
||
268 | av_log(context, AV_LOG_ERROR, "Invalid input \"%s\", you should specify " |
||
269 | "\"auto\" for auto-detection, or the port number.\n", context->filename); |
||
270 | goto fail; |
||
271 | } |
||
272 | |||
273 | if (dv->device_guid) { |
||
274 | if (sscanf(dv->device_guid, "%llx", (long long unsigned int *)&guid) != 1) { |
||
275 | av_log(context, AV_LOG_INFO, "Invalid dvguid parameter: %s\n", |
||
276 | dv->device_guid); |
||
277 | goto fail; |
||
278 | } |
||
279 | } |
||
280 | |||
281 | for (; j < nb_ports && port==-1; ++j) { |
||
282 | raw1394_destroy_handle(dv->raw1394); |
||
283 | |||
284 | if (!(dv->raw1394 = raw1394_new_handle_on_port(j))) { |
||
285 | av_log(context, AV_LOG_ERROR, "Failed setting IEEE1394 port.\n"); |
||
286 | goto fail; |
||
287 | } |
||
288 | |||
289 | for (i=0; i |
||
290 | |||
291 | /* Select device explicitly by GUID */ |
||
292 | |||
293 | if (guid > 1) { |
||
294 | if (guid == rom1394_get_guid(dv->raw1394, i)) { |
||
295 | dv->node = i; |
||
296 | port = j; |
||
297 | break; |
||
298 | } |
||
299 | } else { |
||
300 | |||
301 | /* Select first AV/C tape recorder player node */ |
||
302 | |||
303 | if (rom1394_get_directory(dv->raw1394, i, &rom_dir) < 0) |
||
304 | continue; |
||
305 | if (((rom1394_get_node_type(&rom_dir) == ROM1394_NODE_TYPE_AVC) && |
||
306 | avc1394_check_subunit_type(dv->raw1394, i, AVC1394_SUBUNIT_TYPE_VCR)) || |
||
307 | (rom_dir.unit_spec_id == MOTDCT_SPEC_ID)) { |
||
308 | rom1394_free_directory(&rom_dir); |
||
309 | dv->node = i; |
||
310 | port = j; |
||
311 | break; |
||
312 | } |
||
313 | rom1394_free_directory(&rom_dir); |
||
314 | } |
||
315 | } |
||
316 | } |
||
317 | |||
318 | if (port == -1) { |
||
319 | av_log(context, AV_LOG_ERROR, "No AV/C devices found.\n"); |
||
320 | goto fail; |
||
321 | } |
||
322 | |||
323 | /* Provide bus sanity for multiple connections */ |
||
324 | |||
325 | iec61883_cmp_normalize_output(dv->raw1394, 0xffc0 | dv->node); |
||
326 | |||
327 | /* Find out if device is DV or HDV */ |
||
328 | |||
329 | if (dv->type == IEC61883_AUTO) { |
||
330 | response = avc1394_transaction(dv->raw1394, dv->node, |
||
331 | AVC1394_CTYPE_STATUS | |
||
332 | AVC1394_SUBUNIT_TYPE_TAPE_RECORDER | |
||
333 | AVC1394_SUBUNIT_ID_0 | |
||
334 | AVC1394_VCR_COMMAND_OUTPUT_SIGNAL_MODE | |
||
335 | 0xFF, 2); |
||
336 | response = AVC1394_GET_OPERAND0(response); |
||
337 | dv->type = (response == 0x10 || response == 0x90 || response == 0x1A || response == 0x9A) ? |
||
338 | IEC61883_HDV : IEC61883_DV; |
||
339 | } |
||
340 | |||
341 | /* Connect to device, and do initialization */ |
||
342 | |||
343 | dv->channel = iec61883_cmp_connect(dv->raw1394, dv->node, &dv->output_port, |
||
344 | raw1394_get_local_id(dv->raw1394), |
||
345 | &dv->input_port, &dv->bandwidth); |
||
346 | |||
347 | if (dv->channel < 0) |
||
348 | dv->channel = 63; |
||
349 | |||
350 | if (!dv->max_packets) |
||
351 | dv->max_packets = 100; |
||
352 | |||
353 | if (dv->type == IEC61883_HDV) { |
||
354 | |||
355 | /* Init HDV receive */ |
||
356 | |||
357 | avformat_new_stream(context, NULL); |
||
358 | |||
359 | dv->mpeg_demux = ff_mpegts_parse_open(context); |
||
360 | if (!dv->mpeg_demux) |
||
361 | goto fail; |
||
362 | |||
363 | dv->parse_queue = iec61883_parse_queue_hdv; |
||
364 | |||
365 | dv->iec61883_mpeg2 = iec61883_mpeg2_recv_init(dv->raw1394, |
||
366 | (iec61883_mpeg2_recv_t)iec61883_callback, |
||
367 | dv); |
||
368 | |||
369 | dv->max_packets *= 766; |
||
370 | } else { |
||
371 | |||
372 | /* Init DV receive */ |
||
373 | |||
374 | dv->dv_demux = avpriv_dv_init_demux(context); |
||
375 | if (!dv->dv_demux) |
||
376 | goto fail; |
||
377 | |||
378 | dv->parse_queue = iec61883_parse_queue_dv; |
||
379 | |||
380 | dv->iec61883_dv = iec61883_dv_fb_init(dv->raw1394, iec61883_callback, dv); |
||
381 | } |
||
382 | |||
383 | dv->raw1394_poll.fd = raw1394_get_fd(dv->raw1394); |
||
384 | dv->raw1394_poll.events = POLLIN | POLLERR | POLLHUP | POLLPRI; |
||
385 | |||
386 | /* Actually start receiving */ |
||
387 | |||
388 | if (dv->type == IEC61883_HDV) |
||
389 | iec61883_mpeg2_recv_start(dv->iec61883_mpeg2, dv->channel); |
||
390 | else |
||
391 | iec61883_dv_fb_start(dv->iec61883_dv, dv->channel); |
||
392 | |||
393 | #if THREADS |
||
394 | dv->thread_loop = 1; |
||
395 | pthread_mutex_init(&dv->mutex, NULL); |
||
396 | pthread_cond_init(&dv->cond, NULL); |
||
397 | pthread_create(&dv->receive_task_thread, NULL, iec61883_receive_task, dv); |
||
398 | #endif |
||
399 | |||
400 | return 0; |
||
401 | |||
402 | fail: |
||
403 | raw1394_destroy_handle(dv->raw1394); |
||
404 | return AVERROR(EIO); |
||
405 | } |
||
406 | |||
407 | static int iec61883_read_packet(AVFormatContext *context, AVPacket *pkt) |
||
408 | { |
||
409 | struct iec61883_data *dv = context->priv_data; |
||
410 | int size; |
||
411 | |||
412 | /** |
||
413 | * Try to parse frames from queue |
||
414 | */ |
||
415 | |||
416 | #ifdef THREADS |
||
417 | pthread_mutex_lock(&dv->mutex); |
||
418 | while ((size = dv->parse_queue(dv, pkt)) == -1) |
||
419 | if (!dv->eof) |
||
420 | pthread_cond_wait(&dv->cond, &dv->mutex); |
||
421 | else |
||
422 | break; |
||
423 | pthread_mutex_unlock(&dv->mutex); |
||
424 | #else |
||
425 | int result; |
||
426 | while ((size = dv->parse_queue(dv, pkt)) == -1) { |
||
427 | iec61883_receive_task((void *)dv); |
||
428 | if (dv->receive_error) |
||
429 | return dv->receive_error; |
||
430 | } |
||
431 | #endif |
||
432 | |||
433 | return size; |
||
434 | } |
||
435 | |||
436 | static int iec61883_close(AVFormatContext *context) |
||
437 | { |
||
438 | struct iec61883_data *dv = context->priv_data; |
||
439 | |||
440 | #if THREADS |
||
441 | dv->thread_loop = 0; |
||
442 | pthread_join(dv->receive_task_thread, NULL); |
||
443 | pthread_cond_destroy(&dv->cond); |
||
444 | pthread_mutex_destroy(&dv->mutex); |
||
445 | #endif |
||
446 | |||
447 | if (dv->type == IEC61883_HDV) { |
||
448 | iec61883_mpeg2_recv_stop(dv->iec61883_mpeg2); |
||
449 | iec61883_mpeg2_close(dv->iec61883_mpeg2); |
||
450 | ff_mpegts_parse_close(dv->mpeg_demux); |
||
451 | } else { |
||
452 | iec61883_dv_fb_stop(dv->iec61883_dv); |
||
453 | iec61883_dv_fb_close(dv->iec61883_dv); |
||
454 | } |
||
455 | while (dv->queue_first) { |
||
456 | DVPacket *packet = dv->queue_first; |
||
457 | dv->queue_first = packet->next; |
||
458 | av_free(packet->buf); |
||
459 | av_free(packet); |
||
460 | } |
||
461 | |||
462 | iec61883_cmp_disconnect(dv->raw1394, dv->node, dv->output_port, |
||
463 | raw1394_get_local_id(dv->raw1394), |
||
464 | dv->input_port, dv->channel, dv->bandwidth); |
||
465 | |||
466 | raw1394_destroy_handle(dv->raw1394); |
||
467 | |||
468 | return 0; |
||
469 | } |
||
470 | |||
471 | static const AVOption options[] = { |
||
472 | { "dvtype", "override autodetection of DV/HDV", offsetof(struct iec61883_data, type), AV_OPT_TYPE_INT, {.i64 = IEC61883_AUTO}, IEC61883_AUTO, IEC61883_HDV, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, |
||
473 | { "auto", "auto detect DV/HDV", 0, AV_OPT_TYPE_CONST, {.i64 = IEC61883_AUTO}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, |
||
474 | { "dv", "force device being treated as DV device", 0, AV_OPT_TYPE_CONST, {.i64 = IEC61883_DV}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, |
||
475 | { "hdv" , "force device being treated as HDV device", 0, AV_OPT_TYPE_CONST, {.i64 = IEC61883_HDV}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, |
||
476 | { "dvbuffer", "set queue buffer size (in packets)", offsetof(struct iec61883_data, max_packets), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, |
||
477 | { "dvguid", "select one of multiple DV devices by its GUID", offsetof(struct iec61883_data, device_guid), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, |
||
478 | { NULL }, |
||
479 | }; |
||
480 | |||
481 | static const AVClass iec61883_class = { |
||
482 | .class_name = "iec61883 indev", |
||
483 | .item_name = av_default_item_name, |
||
484 | .option = options, |
||
485 | .version = LIBAVUTIL_VERSION_INT, |
||
486 | }; |
||
487 | |||
488 | AVInputFormat ff_iec61883_demuxer = { |
||
489 | .name = "iec61883", |
||
490 | .long_name = NULL_IF_CONFIG_SMALL("libiec61883 (new DV1394) A/V input device"), |
||
491 | .priv_data_size = sizeof(struct iec61883_data), |
||
492 | .read_header = iec61883_read_header, |
||
493 | .read_packet = iec61883_read_packet, |
||
494 | .read_close = iec61883_close, |
||
495 | .flags = AVFMT_NOFILE, |
||
496 | .priv_class = &iec61883_class, |
||
497 | };>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |