Remove vfunc from port

Update docs
Remove virtual functions from port, we don't want this to be changed.
This commit is contained in:
Wim Taymans 2016-05-09 12:16:04 +02:00
parent 20c50772fa
commit 91385a782e
3 changed files with 102 additions and 163 deletions

View file

@ -7,7 +7,7 @@ and consume media to/from.
Some of the requirements are:
- must be efficient for raw video using fd passing
- must be able to provide media from any process
- must be able to provide/consume/process media from any process
- streaming media only (no seeking)
- policy to restrict access to devices and streams
@ -16,9 +16,7 @@ only and should be able to handle compressed video and other
streamable media as well.
The design is in some part inspired by pulseaudio, hence its original
name. We however are not concerned with playback of any of the media,
this should be handled by a separate consumer rendering the media to
a specific output device.
name. Increasinly we also seem to add functionality of jack.
Objects
@ -46,21 +44,21 @@ DBus protocol
The main daemon is registered on the session bus with name: org.pinos
Various Source1 objects are registered in the server based on the available
sources of content. Source1 has properties and has format descriptions of
Various Node1 objects are registered in the server based on the available
sources or sinks of content. Source1 has properties and has format descriptions of
what it can provide.
First a client needs to register with pinos by calling
org.pinos.Daemon1.ConnectClient(). This creates a new Client1 object that
the client must use for further communication.
A client can then do org.pinos.Client1.CreateSourceOutput() to create a
new SourceOutput1 to retrieve data from a source. It can specify a source
explicitly or let the server choose a source. The client must provide a list
A client can then do org.pinos.Client1.CreateChannel() to create a
new Channel to retrieve/send data from/to a node. It can specify a node/port
explicitly or let the server choose a port. The client must provide a list
of formats it can handle along with extra properties that can help with
selecting an appropriate source.
selecting an appropriate port.
A client can then call org.pinos.SourceOutput1.Start() to negotiate the final
A client can then call org.pinos.Channel1.Start() to negotiate the final
media format and start the data transfer. A new fd is returned to the client
along with the negotiated format and properties.
@ -82,36 +80,30 @@ managed.
* server side
v4l2src pinospay multisocketsink
| | |
| | |
make buffer |--------->| |
| | (1) |
| |------------>| (2) ----->
| | |
| |<------------|
| (4)| ............| (3)
| | |
|... | ... |
| | |
| |<------------| (5) <-----
| (6)| |
| | |
v4l2src pinossocketsink
| |
| |
make buffer |--------->|
| | (1)
| | (2) ----->
| | (3)
|... | ...
| |
| | (4) <-----
|<---------|
(1) pinospay generates the pinos message for the v4l2 input
buffer. It is assumed in the next steps that the payloader
(1) pinossocketsink generates the pinos message from the v4l2 input
buffer. It is assumed in the next steps that the sink
receives fd-memory from v4l2src and that the memory is only
freed again when no clients are looking at the fd.
(2) multisocketsink sends the buffer to N Pinos clients
(3) for each client that is sent a buffer, multisocketsink sends an
event with the client object and buffer in it.
(4) pinospay uses the fdmanager object to map the fd-index that was
(2) pinossocketsink sends the buffer to N Pinos clients
(3) for each client that is sent a buffer, pinossocketsink uses the
fdmanager object to map the fd-index that was
sent, to the buffer and client. The buffer is reffed and kept
alive for as long as the client is using the buffer.
(5) when a message is received from a client, multisocketsink sends an
event upstream.
(6) pinospay parses the message and instructs the fdmanager to release
(4) when a message is received from a client, pinossocketsink
parses the message and instructs the fdmanager to release
the fd-index again. When all clients release the fd, the buffer
will be unreffed and v4l2src can reuse the memory.
@ -157,34 +149,33 @@ make buffer |--------->| |
* client producer, server side
socketsrc pinospay multisocketsink
| | |
------> (1) | (2)| |
|----------->| |
| |------------>| (3) -------->
| | | ....
| (5)|<------------| (4)
| | ...... |
| | |
| (7)|<------------| (6) <--------
<------- (8)|<-----------| |
| | |
socketsrc pinossocketsink
| |
------> (1) | (2)|
|----------->|
| | (3) -------->
| | ....
| (4)|
| | ....
| |
| (6)| (5) <--------
<------- (7)|<-----------|
| |
(1) pinos buffer arrives from a client. socketsrc wraps the
fd
(2) pinospay sets a weak-ref on the buffer to know when it is
(2) pinossocketsink sets a weak-ref on the buffer to know when it is
freed.
(3) multisocketsink sends the buffer to the clients
(4) for each buffer that is sent, an event is sent to the payloader
(5) the payloader uses the fdmanager to map the fd-index to a buffer
and a client. it keeps a ref on the buffer
(6) release-fd is received from a client
(7) pinospay removes the fd-index from the fdmanager. If all
(3) pinossocketsink sends the buffer to the clients
(4) for each buffer that is sent, the sink uses the fdmanager to map the
fd-index to a buffer and a client. it keeps a ref on the buffer
(5) release-fd is received from a client
(6) pinossocketsink removes the fd-index from the fdmanager. If all
clients released the fd, the buffer will be freeds, triggering
the DestroyNotify. This will then trigger an event with a release-fd
message to the source.
(8) the source sends the release-fd message to Pinos
(7) the source sends the release-fd message to Pinos
* client remove

View file

@ -256,79 +256,6 @@ pinos_port_finalize (GObject * object)
G_OBJECT_CLASS (pinos_port_parent_class)->finalize (object);
}
static void
handle_remove_channel (PinosChannel *channel,
gpointer user_data)
{
PinosPort *port = user_data;
pinos_port_release_channel (port, channel);
}
static PinosChannel *
default_create_channel (PinosPort *port,
const gchar *client_path,
GBytes *format_filter,
PinosProperties *props,
GError **error)
{
PinosPortPrivate *priv = port->priv;
PinosChannel *channel;
GBytes *possible_formats;
possible_formats = pinos_port_get_formats (port, format_filter, error);
if (possible_formats == NULL)
return NULL;
channel = g_object_new (PINOS_TYPE_CHANNEL, "daemon", priv->daemon,
"client-path", client_path,
"direction", priv->direction,
"port-path", priv->object_path,
"possible-formats", possible_formats,
"properties", props,
NULL);
g_bytes_unref (possible_formats);
if (channel == NULL)
goto no_channel;
g_signal_connect (channel,
"remove",
(GCallback) handle_remove_channel,
port);
priv->channels = g_list_prepend (priv->channels, channel);
return g_object_ref (channel);
/* ERRORS */
no_channel:
{
if (error)
*error = g_error_new (G_IO_ERROR,
G_IO_ERROR_FAILED,
"Could not create channel");
return NULL;
}
}
static gboolean
default_release_channel (PinosPort *port,
PinosChannel *channel)
{
PinosPortPrivate *priv = port->priv;
GList *find;
find = g_list_find (priv->channels, channel);
if (find == NULL)
return FALSE;
priv->channels = g_list_delete_link (priv->channels, find);
g_object_unref (channel);
return TRUE;
}
static void
pinos_port_class_init (PinosPortClass * klass)
{
@ -443,9 +370,6 @@ pinos_port_class_init (PinosPortClass * klass)
1,
PINOS_TYPE_CHANNEL);
klass->create_channel = default_create_channel;
klass->release_channel = default_release_channel;
}
static void
@ -591,6 +515,15 @@ pinos_port_get_channels (PinosPort *port)
return priv->channels;
}
static void
handle_remove_channel (PinosChannel *channel,
gpointer user_data)
{
PinosPort *port = user_data;
pinos_port_release_channel (port, channel);
}
/**
* pinos_port_create_channel:
* @port: a #PinosPort
@ -612,27 +545,49 @@ pinos_port_create_channel (PinosPort *port,
PinosProperties *props,
GError **error)
{
PinosPortClass *klass;
PinosPortPrivate *priv;
PinosChannel *channel;
GBytes *possible_formats;
g_return_val_if_fail (PINOS_IS_PORT (port), NULL);
priv = port->priv;
klass = PINOS_PORT_GET_CLASS (port);
possible_formats = pinos_port_get_formats (port, format_filter, error);
if (possible_formats == NULL)
return NULL;
if (klass->create_channel) {
channel = klass->create_channel (port, client_path, format_filter, props, error);
if (channel)
g_signal_emit (port, signals[SIGNAL_CHANNEL_ADDED], 0, channel);
} else {
if (error) {
channel = g_object_new (PINOS_TYPE_CHANNEL, "daemon", priv->daemon,
"client-path", client_path,
"direction", priv->direction,
"port-path", priv->object_path,
"possible-formats", possible_formats,
"properties", props,
NULL);
g_bytes_unref (possible_formats);
if (channel == NULL)
goto no_channel;
g_signal_connect (channel,
"remove",
(GCallback) handle_remove_channel,
port);
priv->channels = g_list_prepend (priv->channels, channel);
g_signal_emit (port, signals[SIGNAL_CHANNEL_ADDED], 0, channel);
return g_object_ref (channel);
/* ERRORS */
no_channel:
{
if (error)
*error = g_error_new (G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"CreateChannel not implemented");
}
channel = NULL;
G_IO_ERROR_FAILED,
"Could not create channel");
return NULL;
}
return channel;
}
/**
@ -648,20 +603,21 @@ gboolean
pinos_port_release_channel (PinosPort *port,
PinosChannel *channel)
{
PinosPortClass *klass;
gboolean res;
PinosPortPrivate *priv;
GList *find;
g_return_val_if_fail (PINOS_IS_PORT (port), FALSE);
g_return_val_if_fail (PINOS_IS_CHANNEL (channel), FALSE);
priv = port->priv;
klass = PINOS_PORT_GET_CLASS (port);
find = g_list_find (priv->channels, channel);
if (find == NULL)
return FALSE;
if (klass->release_channel) {
g_signal_emit (port, signals[SIGNAL_CHANNEL_REMOVED], 0, channel);
res = klass->release_channel (port, channel);
}
else
res = FALSE;
priv->channels = g_list_delete_link (priv->channels, find);
return res;
g_signal_emit (port, signals[SIGNAL_CHANNEL_REMOVED], 0, channel);
g_object_unref (channel);
return TRUE;
}

View file

@ -62,14 +62,6 @@ struct _PinosPort {
*/
struct _PinosPortClass {
GObjectClass parent_class;
PinosChannel * (*create_channel) (PinosPort *port,
const gchar *client_path,
GBytes *format_filter,
PinosProperties *props,
GError **error);
gboolean (*release_channel) (PinosPort *port,
PinosChannel *channel);
};
/* normal GObject stuff */