From 15b02ddee033aec69e75e2c1cdc3de085133d959 Mon Sep 17 00:00:00 2001 From: Georg Lippitsch Date: Thu, 12 Jul 2012 23:36:05 +0200 Subject: [PATCH] Update iec61883 to handle multiple devices, and allow selection of DV device by its GUID --- doc/indevs.texi | 7 ++++++ libavdevice/iec61883.c | 57 ++++++++++++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 8ac102b274..6ccd12c8e3 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -224,6 +224,13 @@ Set maxiumum size of buffer for incoming data, in frames. For DV, this is an exact value. For HDV, it is not frame exact, since HDV does not have a fixed frame size. +@item dvguid +Select the capture device by specifying it's GUID. Capturing will only +be performed from the specified device and fails if no device with the +given GUID is found. This is useful to select the input if multiple +devices are connected at the same time. +Look at /sys/bus/firewire/devices to find out the GUIDs. + @end table @subsection Examples diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c index 8c9a39f305..a63566e9d4 100644 --- a/libavdevice/iec61883.c +++ b/libavdevice/iec61883.c @@ -67,6 +67,8 @@ struct iec61883_data { DVPacket *queue_first; ///< first element of packet queue DVPacket *queue_last; ///< last element of packet queue + char *device_guid; ///< to select one of multiple DV devices + int packets; ///< Number of packets queued int max_packets; ///< Max. number of packets in queue @@ -138,7 +140,7 @@ static int iec61883_callback(unsigned char *data, int length, exit: #ifdef THREADS - pthread_cond_signal(&dv->cond); + pthread_cond_broadcast(&dv->cond); pthread_mutex_unlock(&dv->mutex); #endif return ret; @@ -169,7 +171,7 @@ static void *iec61883_receive_task(void *opaque) #ifdef THREADS pthread_mutex_lock(&dv->mutex); dv->eof = 1; - pthread_cond_signal(&dv->cond); + pthread_cond_broadcast(&dv->cond); pthread_mutex_unlock(&dv->mutex); #else dv->eof = 1; @@ -239,6 +241,7 @@ static int iec61883_read_header(AVFormatContext *context) int port = -1; int response; int i, j = 0; + uint64_t guid = 0; dv->input_port = -1; dv->output_port = -1; @@ -267,25 +270,48 @@ static int iec61883_read_header(AVFormatContext *context) goto fail; } - /* Select first AV/C tape recorder player node */ + if (dv->device_guid) { + if (sscanf(dv->device_guid, "%llx", (long long unsigned int *)&guid) != 1) { + av_log(context, AV_LOG_INFO, "Invalid dvguid parameter: %s\n", + dv->device_guid); + goto fail; + } + } for (; j < nb_ports && port==-1; ++j) { - if (raw1394_set_port(dv->raw1394, j)) { + raw1394_destroy_handle(dv->raw1394); + + if (!(dv->raw1394 = raw1394_new_handle_on_port(j))) { av_log(context, AV_LOG_ERROR, "Failed setting IEEE1394 port.\n"); goto fail; } + for (i=0; iraw1394); ++i) { - if (rom1394_get_directory(dv->raw1394, i, &rom_dir) < 0) - continue; - if (((rom1394_get_node_type(&rom_dir) == ROM1394_NODE_TYPE_AVC) && - avc1394_check_subunit_type(dv->raw1394, i, AVC1394_SUBUNIT_TYPE_VCR)) || - (rom_dir.unit_spec_id == MOTDCT_SPEC_ID)) { + + /* Select device explicitly by GUID */ + + if (guid > 1) { + if (guid == rom1394_get_guid(dv->raw1394, i)) { + dv->node = i; + port = j; + break; + } + } else { + + /* Select first AV/C tape recorder player node */ + + if (rom1394_get_directory(dv->raw1394, i, &rom_dir) < 0) + continue; + if (((rom1394_get_node_type(&rom_dir) == ROM1394_NODE_TYPE_AVC) && + avc1394_check_subunit_type(dv->raw1394, i, AVC1394_SUBUNIT_TYPE_VCR)) || + (rom_dir.unit_spec_id == MOTDCT_SPEC_ID)) { + rom1394_free_directory(&rom_dir); + dv->node = i; + port = j; + break; + } rom1394_free_directory(&rom_dir); - dv->node = i; - port = j; - break; } - rom1394_free_directory(&rom_dir); } } @@ -294,6 +320,10 @@ static int iec61883_read_header(AVFormatContext *context) goto fail; } + /* Provide bus sanity for multiple connections */ + + iec61883_cmp_normalize_output(dv->raw1394, 0xffc0 | dv->node); + /* Find out if device is DV or HDV */ if (dv->type == IEC61883_AUTO) { @@ -444,6 +474,7 @@ static const AVOption options[] = { { "dv", "force device being treated as DV device", 0, AV_OPT_TYPE_CONST, {.i64 = IEC61883_DV}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, { "hdv" , "force device being treated as HDV device", 0, AV_OPT_TYPE_CONST, {.i64 = IEC61883_HDV}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, { "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 }, + { "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 }, { NULL }, };