summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/indevs.texi7
-rw-r--r--libavdevice/iec61883.c57
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; i<raw1394_get_nodecount(dv->raw1394); ++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 },
};