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

View file

@ -256,79 +256,6 @@ pinos_port_finalize (GObject * object)
G_OBJECT_CLASS (pinos_port_parent_class)->finalize (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 static void
pinos_port_class_init (PinosPortClass * klass) pinos_port_class_init (PinosPortClass * klass)
{ {
@ -443,9 +370,6 @@ pinos_port_class_init (PinosPortClass * klass)
1, 1,
PINOS_TYPE_CHANNEL); PINOS_TYPE_CHANNEL);
klass->create_channel = default_create_channel;
klass->release_channel = default_release_channel;
} }
static void static void
@ -591,6 +515,15 @@ pinos_port_get_channels (PinosPort *port)
return priv->channels; 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: * pinos_port_create_channel:
* @port: a #PinosPort * @port: a #PinosPort
@ -612,27 +545,49 @@ pinos_port_create_channel (PinosPort *port,
PinosProperties *props, PinosProperties *props,
GError **error) GError **error)
{ {
PinosPortClass *klass; PinosPortPrivate *priv;
PinosChannel *channel; PinosChannel *channel;
GBytes *possible_formats;
g_return_val_if_fail (PINOS_IS_PORT (port), NULL); 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 = g_object_new (PINOS_TYPE_CHANNEL, "daemon", priv->daemon,
channel = klass->create_channel (port, client_path, format_filter, props, error); "client-path", client_path,
if (channel) "direction", priv->direction,
g_signal_emit (port, signals[SIGNAL_CHANNEL_ADDED], 0, channel); "port-path", priv->object_path,
} else { "possible-formats", possible_formats,
if (error) { "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, *error = g_error_new (G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED, G_IO_ERROR_FAILED,
"CreateChannel not implemented"); "Could not create channel");
} return NULL;
channel = NULL;
} }
return channel;
} }
/** /**
@ -648,20 +603,21 @@ gboolean
pinos_port_release_channel (PinosPort *port, pinos_port_release_channel (PinosPort *port,
PinosChannel *channel) PinosChannel *channel)
{ {
PinosPortClass *klass; PinosPortPrivate *priv;
gboolean res; GList *find;
g_return_val_if_fail (PINOS_IS_PORT (port), FALSE); g_return_val_if_fail (PINOS_IS_PORT (port), FALSE);
g_return_val_if_fail (PINOS_IS_CHANNEL (channel), 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) { priv->channels = g_list_delete_link (priv->channels, find);
g_signal_emit (port, signals[SIGNAL_CHANNEL_REMOVED], 0, channel);
res = klass->release_channel (port, channel);
}
else
res = FALSE;
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 { struct _PinosPortClass {
GObjectClass parent_class; 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 */ /* normal GObject stuff */