summaryrefslogtreecommitdiffstats
path: root/ext/raw1394
diff options
context:
space:
mode:
Diffstat (limited to 'ext/raw1394')
-rw-r--r--ext/raw1394/gstdv1394src.c193
-rw-r--r--ext/raw1394/gstdv1394src.h8
2 files changed, 178 insertions, 23 deletions
diff --git a/ext/raw1394/gstdv1394src.c b/ext/raw1394/gstdv1394src.c
index 1b6b0204..473e0884 100644
--- a/ext/raw1394/gstdv1394src.c
+++ b/ext/raw1394/gstdv1394src.c
@@ -1,6 +1,7 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* <2000> Daniel Fischer <dan@f3c.com>
+ * <2004> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -23,6 +24,10 @@
#endif
#include <gst/gst.h>
#include <string.h>
+#include <libavc1394/avc1394.h>
+#include <libavc1394/avc1394_vcr.h>
+#include <libavc1394/rom1394.h>
+
#include "gstdv1394src.h"
#define N_BUFFERS_IN_POOL 3
@@ -37,12 +42,24 @@ enum
LAST_SIGNAL
};
+#define DEFAULT_PORT -1
+#define DEFAULT_CHANNEL 63
+#define DEFAULT_CONSECUTIVE 1
+#define DEFAULT_SKIP 0
+#define DEFAULT_DROP_INCOMPLETE TRUE
+#define DEFAULT_USE_AVC TRUE
+#define DEFAULT_GUID 0
+
enum
{
ARG_0,
+ ARG_PORT,
+ ARG_CHANNEL,
ARG_CONSECUTIVE,
ARG_SKIP,
- ARG_DROP_INCOMPLETE
+ ARG_DROP_INCOMPLETE,
+ ARG_USE_AVC,
+ ARG_GUID
};
static GstElementDetails gst_dv1394src_details =
@@ -50,7 +67,7 @@ GST_ELEMENT_DETAILS ("Firewire (1394) DV Source",
"Source/Video",
"Source for DV video data from firewire port",
"Erik Walthinsen <omega@temple-baptist.com>\n"
- "Daniel Fischer <dan@f3c.com>");
+ "Daniel Fischer <dan@f3c.com>\n" "Wim Taymans <wim@fluendo.com>");
#if 0
static GstPadTemplate *
@@ -132,16 +149,31 @@ gst_dv1394src_class_init (GstDV1394SrcClass * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PORT,
+ g_param_spec_int ("port", "Port", "Port number (-1 automatic)",
+ -1, 16, DEFAULT_PORT, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CHANNEL,
+ g_param_spec_int ("channel", "Channel", "Channel number for listening",
+ 0, 64, DEFAULT_CHANNEL, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CONSECUTIVE,
g_param_spec_int ("consecutive", "consecutive frames",
- "send n consecutive frames after skipping", 1, G_MAXINT, 1,
- G_PARAM_READWRITE));
+ "send n consecutive frames after skipping", 1, G_MAXINT,
+ DEFAULT_CONSECUTIVE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SKIP,
- g_param_spec_int ("skip", "skip frames", "skip n frames", 0, G_MAXINT, 1,
- G_PARAM_READWRITE));
+ g_param_spec_int ("skip", "skip frames", "skip n frames",
+ 0, G_MAXINT, DEFAULT_SKIP, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DROP_INCOMPLETE,
g_param_spec_boolean ("drop_incomplete", "drop_incomplete",
- "drop incomplete frames", TRUE, G_PARAM_READWRITE));
+ "drop incomplete frames", DEFAULT_DROP_INCOMPLETE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_USE_AVC,
+ g_param_spec_boolean ("use-avc", "Use AV/C", "Use AV/C VTR control",
+ DEFAULT_USE_AVC, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_GUID,
+ g_param_spec_uint64 ("guid", "GUID",
+ "select one of multiple DV devices by its GUID. use a hexadecimal "
+ "like 0xhhhhhhhhhhhhhhhh. (0 = no guid)", 0, G_MAXUINT64,
+ DEFAULT_GUID, G_PARAM_READWRITE));
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
@@ -159,13 +191,14 @@ gst_dv1394src_init (GstDV1394Src * dv1394src)
gst_pad_use_explicit_caps (dv1394src->srcpad);
gst_element_add_pad (GST_ELEMENT (dv1394src), dv1394src->srcpad);
- dv1394src->card = 0;
- dv1394src->port = 0;
- dv1394src->channel = 63;
+ dv1394src->port = DEFAULT_PORT;
+ dv1394src->channel = DEFAULT_CHANNEL;
- dv1394src->consecutive = 1;
- dv1394src->skip = 0;
- dv1394src->drop_incomplete = TRUE;
+ dv1394src->consecutive = DEFAULT_CONSECUTIVE;
+ dv1394src->skip = DEFAULT_SKIP;
+ dv1394src->drop_incomplete = DEFAULT_DROP_INCOMPLETE;
+ dv1394src->use_avc = DEFAULT_USE_AVC;
+ dv1394src->guid = DEFAULT_GUID;
/* initialized when first header received */
dv1394src->frameSize = 0;
@@ -186,6 +219,12 @@ gst_dv1394src_set_property (GObject * object, guint prop_id,
filter = GST_DV1394SRC (object);
switch (prop_id) {
+ case ARG_PORT:
+ filter->port = g_value_get_int (value);
+ break;
+ case ARG_CHANNEL:
+ filter->channel = g_value_get_int (value);
+ break;
case ARG_SKIP:
filter->skip = g_value_get_int (value);
break;
@@ -195,6 +234,12 @@ gst_dv1394src_set_property (GObject * object, guint prop_id,
case ARG_DROP_INCOMPLETE:
filter->drop_incomplete = g_value_get_boolean (value);
break;
+ case ARG_USE_AVC:
+ filter->use_avc = g_value_get_boolean (value);
+ break;
+ case ARG_GUID:
+ filter->guid = g_value_get_uint64 (value);
+ break;
default:
break;
}
@@ -211,6 +256,12 @@ gst_dv1394src_get_property (GObject * object, guint prop_id, GValue * value,
filter = GST_DV1394SRC (object);
switch (prop_id) {
+ case ARG_PORT:
+ g_value_set_int (value, filter->port);
+ break;
+ case ARG_CHANNEL:
+ g_value_set_int (value, filter->channel);
+ break;
case ARG_SKIP:
g_value_set_int (value, filter->skip);
break;
@@ -220,6 +271,12 @@ gst_dv1394src_get_property (GObject * object, guint prop_id, GValue * value,
case ARG_DROP_INCOMPLETE:
g_value_set_boolean (value, filter->drop_incomplete);
break;
+ case ARG_USE_AVC:
+ g_value_set_boolean (value, filter->use_avc);
+ break;
+ case ARG_GUID:
+ g_value_set_uint64 (value, filter->guid);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -323,7 +380,7 @@ gst_dv1394src_iso_receive (raw1394handle_t handle, int channel, size_t len,
dif_block) * 80, p, 480);
break;
- default: /* we canīt handle any other data */
+ default: /* we can't handle any other data */
break;
}
dv1394src->bytesInFrame += 480;
@@ -353,6 +410,73 @@ gst_dv1394src_get (GstPad * pad)
return GST_DATA (dv1394src->buf);
}
+static int
+gst_dv1394src_discover_avc_node (GstDV1394Src * src)
+{
+ int node = -1;
+ int i, j = 0;
+ int m = src->num_ports;
+
+ if (src->port >= 0) {
+ /* search on explicit port */
+ j = src->port;
+ m = j + 1;
+ }
+
+ /* loop over all our ports */
+ for (; j < m && node == -1; j++) {
+ raw1394handle_t handle;
+ gint n_ports;
+ struct raw1394_portinfo pinf[16];
+
+ /* open the port */
+ handle = raw1394_new_handle ();
+ if (!handle) {
+ g_warning ("raw1394 - failed to get handle: %s.\n", strerror (errno));
+ continue;
+ }
+ if ((n_ports = raw1394_get_port_info (handle, pinf, 16)) < 0) {
+ g_warning ("raw1394 - failed to get port info: %s.\n", strerror (errno));
+ goto next;
+ }
+
+ /* tell raw1394 which host adapter to use */
+ if (raw1394_set_port (handle, j) < 0) {
+ g_warning ("raw1394 - failed to set set port: %s.\n", strerror (errno));
+ goto next;
+ }
+
+ /* now loop over all the nodes */
+ for (i = 0; i < raw1394_get_nodecount (handle); i++) {
+ /* are we looking for an explicit GUID */
+ if (src->guid != 0) {
+ if (src->guid == rom1394_get_guid (handle, i)) {
+ node = i;
+ src->port = j;
+ break;
+ }
+ } else {
+ rom1394_directory rom_dir;
+
+ /* select first AV/C Tape Reccorder Player node */
+ if (rom1394_get_directory (handle, i, &rom_dir) < 0) {
+ g_warning ("error reading config rom directory for node %d\n", i);
+ continue;
+ }
+ if ((rom1394_get_node_type (&rom_dir) == ROM1394_NODE_TYPE_AVC) &&
+ avc1394_check_subunit_type (handle, i, AVC1394_SUBUNIT_TYPE_VCR)) {
+ node = i;
+ src->port = j;
+ break;
+ }
+ }
+ }
+ next:
+ raw1394_destroy_handle (handle);
+ }
+ return node;
+}
+
static GstElementStateReturn
gst_dv1394src_change_state (GstElement * element)
{
@@ -363,34 +487,41 @@ gst_dv1394src_change_state (GstElement * element)
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
+ /* create a handle */
if ((dv1394src->handle = raw1394_new_handle ()) == NULL) {
GST_ELEMENT_ERROR (dv1394src, RESOURCE, NOT_FOUND, (NULL),
("can't get raw1394 handle"));
return GST_STATE_FAILURE;
}
+ /* set this plugin as the user data */
raw1394_set_userdata (dv1394src->handle, dv1394src);
- dv1394src->numcards =
+ /* get number of ports */
+ dv1394src->num_ports =
raw1394_get_port_info (dv1394src->handle, dv1394src->pinfo, 16);
- if (dv1394src->numcards == 0) {
+ if (dv1394src->num_ports == 0) {
GST_ELEMENT_ERROR (dv1394src, RESOURCE, NOT_FOUND, (NULL),
- ("no cards available for raw1394"));
+ ("no ports available for raw1394"));
return GST_STATE_FAILURE;
}
- if (dv1394src->pinfo[dv1394src->card].nodes <= 1) {
- GST_ELEMENT_ERROR (dv1394src, RESOURCE, NOT_FOUND, (NULL),
- ("there are no nodes on the 1394 bus"));
- return GST_STATE_FAILURE;
+
+ if (dv1394src->use_avc || dv1394src->port == -1) {
+ /* discover AVC and optionally the port */
+ dv1394src->avc_node = gst_dv1394src_discover_avc_node (dv1394src);
}
+
+ /* configure our port now */
if (raw1394_set_port (dv1394src->handle, dv1394src->port) < 0) {
GST_ELEMENT_ERROR (dv1394src, RESOURCE, SETTINGS, (NULL),
("can't set 1394 port %d", dv1394src->port));
return GST_STATE_FAILURE;
}
+ /* set the callbacks */
raw1394_set_iso_handler (dv1394src->handle, dv1394src->channel,
gst_dv1394src_iso_receive);
raw1394_set_bus_reset_handler (dv1394src->handle,
gst_dv1394src_bus_reset);
dv1394src->started = FALSE;
+
GST_DEBUG_OBJECT (dv1394src, "successfully opened up 1394 connection");
break;
case GST_STATE_PAUSED_TO_PLAYING:
@@ -399,11 +530,31 @@ gst_dv1394src_change_state (GstElement * element)
("can't start 1394 iso receive"));
return GST_STATE_FAILURE;
}
+ if (dv1394src->use_avc) {
+ /* start the VCR */
+ if (!avc1394_vcr_is_recording (dv1394src->handle, dv1394src->avc_node)
+ && avc1394_vcr_is_playing (dv1394src->handle, dv1394src->avc_node)
+ != AVC1394_VCR_OPERAND_PLAY_FORWARD) {
+ avc1394_vcr_play (dv1394src->handle, dv1394src->avc_node);
+ }
+ }
break;
case GST_STATE_PLAYING_TO_PAUSED:
raw1394_stop_iso_rcv (dv1394src->handle, dv1394src->channel);
+ if (dv1394src->use_avc) {
+ /* pause the VCR */
+ if (!avc1394_vcr_is_recording (dv1394src->handle, dv1394src->avc_node)
+ && (avc1394_vcr_is_playing (dv1394src->handle, dv1394src->avc_node)
+ != AVC1394_VCR_OPERAND_PLAY_FORWARD_PAUSE)) {
+ avc1394_vcr_pause (dv1394src->handle, dv1394src->avc_node);
+ }
+ }
break;
case GST_STATE_READY_TO_NULL:
+ if (dv1394src->use_avc) {
+ /* stop the VCR */
+ avc1394_vcr_stop (dv1394src->handle, dv1394src->avc_node);
+ }
raw1394_destroy_handle (dv1394src->handle);
break;
default:
diff --git a/ext/raw1394/gstdv1394src.h b/ext/raw1394/gstdv1394src.h
index 7d384fd0..eded0b78 100644
--- a/ext/raw1394/gstdv1394src.h
+++ b/ext/raw1394/gstdv1394src.h
@@ -55,8 +55,12 @@ struct _GstDV1394Src {
gint skip;
gboolean drop_incomplete;
- int numcards,numports;
- int card,port,channel;
+ gint num_ports;
+ gint port;
+ gint channel;
+ octlet_t guid;
+ gint avc_node;
+ gboolean use_avc;
struct raw1394_portinfo pinfo[16];
raw1394handle_t handle;