Commit Graph

21 Commits

Author SHA1 Message Date
Joshua Colp 7528b86cad stream: Make the topology a reference counted object.
The stream topology has no lock of its own resulting in
another lock protecting it in some way (for example the
channel lock). If multiple channels are being juggled at
the same time this can be problematic. This change makes
the topology a reference counted object instead which
guarantees it will remain valid even without the channel
lock being held.

Change-Id: I4f4d3dd856a033ed55fe218c3a4fab364afedb03
2018-05-03 16:31:56 +00:00
George Joseph f79a372941 streams: Add string metadata capability
Replaces the never used opaque data array.

Updated stream tests to include get/set metadata and
stream clone with metadata.

Added stream metadata dump to "core show channel"

Change-Id: Id7473aa4b374d7ab53046c20e321037ba9a56863
2018-04-17 11:03:55 -06:00
Corey Farrell fb18895108 stream: Return error from ast_stream_topology_set_stream.
ast_stream_topology_set_stream had suppressed error codes from
AST_VECTOR_APPEND.  The result of AST_VECTOR_APPEND needs to be returned
to the caller so they can take appropriate action on the stream.

Change-Id: I6c0d12755743eadba1357f6153526cc055592856
2017-11-07 11:28:53 -05:00
Joshua Colp 4c535f5c30 core / pjsip: Add support for grouping streams together.
In WebRTC streams (or media tracks in their world) can be grouped
together using the mslabel. This informs the browser that each
should be synchronized with each other.

This change extends the stream API so this information can
be stored with streams. The PJSIP support has been extended
to use the mslabel to determine grouped streams and store
this association on the streams. Finally when creating the
SDP the group information is used to cause each media stream
to use the same mslabel.

ASTERISK-27379

Change-Id: Id6299aa031efe46254edbdc7973c534d54d641ad
2017-10-30 17:10:03 -05:00
Joshua Colp 8412cc1e07 Merge "SDP: Rework SDP offer/answer model and update capabilities merges." 2017-07-26 08:20:35 -05:00
Mark Michelson 45df25a579 chan_pjsip: Add support for multiple streams of the same type.
The stream topology (list of streams and order) is now stored with the
configured PJSIP endpoints and used during the negotiation process.

Media negotiation state information has been changed to be stored
in a separate object. Two of these objects exist at any one time
on a session. The active media state information is what was previously
negotiated and the pending media state information is what the
media state will become if negotiation succeeds. Streams and other
state information is stored in this object using the index (or
position) of each individual stream for easy lookup.

The ability for a media type handler to specify a callback for
writing has been added as well as the ability to add file
descriptors with a callback which is invoked when data is available
to be read on them. This allows media logic to live outside of
the chan_pjsip module.

Direct media has been changed so that only the first audio and
video stream are directly connected. In the future once the RTP
engine glue API has been updated to know about streams each individual
stream can be directly connected as appropriate.

Media negotiation itself will currently answer all the provided streams
on an offer within configured limits and on an offer will use the
topology created as a result of the disallow/allow codec lines.

If a stream has been removed or declined we will now mark it as such
within the resulting SDP.

Applications can now also request that the stream topology change.
If we are told to do so we will limit any provided formats to the ones
configured on the endpoint and send a re-invite with the new topology.

Two new configuration options have also been added to PJSIP endpoints:

max_audio_streams: determines the maximum number of audio streams to
offer/accept from an endpoint. Defaults to 1.

max_video_streams: determines the maximum number of video streams to
offer/accept from an endpoint. Defaults to 1.

ASTERISK-27076

Change-Id: I8afd8dd2eb538806a39b887af0abd046266e14c7
2017-06-28 18:36:29 +00:00
Richard Mudgett 3a18a09030 SDP: Rework SDP offer/answer model and update capabilities merges.
The SDP offer/answer model requires an answer to an offer before a new SDP
can be processed.  This allows our local SDP creation to be deferred until
we know that we need to create an offer or an answer SDP.  Once the local
SDP is created it won't change until the SDP negotiation is restarted.

An offer SDP in an initial SIP INVITE can receive more than one answer
SDP.  In this case, we need to merge each answer SDP with our original
offer capabilities to get the currently negotiated capabilities.  To
satisfy this requirement means that we cannot update our proposed
capabilities until the negotiations are restarted.

Local topology updates from ast_sdp_state_update_local_topology() are
merged together until the next offer SDP is created.  These accumulated
updates are then merged with the current negotiated capabilities to create
the new proposed capabilities that the offer SDP is built.

Local topology updates are merged in several passes to attempt to be smart
about how streams from the system are matched with the previously
negotiated stream slots.  To allow for T.38 support when merging, type
matching considers audio and image types to be equivalent.  First streams
are matched by stream name and type.  Then streams are matched by stream
type only.  Any remaining unmatched existing streams are declined.  Any
new active streams are either backfilled into pre-merge declined slots or
appended onto the end of the merged topology.  Any excess new streams
above the maximum supported number of streams are simply discarded.

Remote topology negotiation merges depend if the topology is an offer or
answer.  An offer remote topology negotiation dictates the stream slot
ordering and new streams can be added.  A remote offer can do anything to
the previously negotiated streams except reduce the number of stream
slots.  An answer remote topology negotiation is limited to what our offer
requested.  The answer can only decline streams, pick codecs from the
offered list, or indicate the remote's stream hold state.

I had originally kept the RTP instance if the remote offer SDP changed a
stream type between audio and video since they both use RTP.  However, I
later removed this support in favor of simply creating a new RTP instance
since the stream's purpose has to be changing anyway.  Any RTP packets
from the old stream type might cause mischief for the bridged peer.

* Added ast_sdp_state_restart_negotiations() to restart the SDP
offer/answer negotiations.  We will thus know to create a new local SDP
when it is time to create an offer or answer.

* Removed ast_sdp_state_reset().  Save the current topology before
starting T.38.  To recover from T.38 simply update the local topology to
the saved topology and restart the SDP negotiations to get the offer SDP
renegotiating the previous configuration.

* Allow initial topology for ast_sdp_state_alloc() to be NULL so an
initial remote offer SDP can dictate the streams we start with.  We can
always update the local topology later if it turns out we need to offer
SDP first because the remote chose to defer sending us a SDP.

* Made the ast_sdp_state_alloc() initial topology limit to max_streams,
limit to configured codecs, handle declined streams, and discard
unsupported types.

* Convert struct ast_sdp to ao2 object.  Needed to easily save off a
remote SDP to refer to later for various reasons such as generating
declined m= lines in the local SDP.

* Improve converting remote SDP streams to a topology including stream
state.  A stream state of AST_STREAM_STATE_REMOVED indicates the stream is
declined/dead.

* Improve merging streams to take into account the stream state.

* Added query for remote hold state.

* Added maximum streams allowed SDP config option.

* Added ability to create new streams as needed.  New streams are created
with configured default audio, video, or image codecs depending on stream
type.

* Added global locally_held state along with a per stream local hold
state.  Historically, Asterisk only has a global locally held state
because when the we put the remote on hold we do it for all active
streams.

* Added queries for a rejected offer and current SDP negotiation role.
The rejected query allows the using module to know how to respond to a
failed remote SDP set.  Should the using module respond with a 488 Not
Acceptable Here or 500 Internal Error to the offer SDP?

* Moved sdp_state_capabilities.connection_address to ast_sdp_state.  There
seems no reason to keep it in the sdp_state_capabilities struct since it
was only used by the ast_sdp_state.proposed_capabilities instance.

* Callbacks are now available to allow the using module some customization
of negotiated streams and to complete setting up streams for use.  See the
typedef doxygen for each callback for what is allowable and when they are
called.
    * Added topology answerer modify callback.
    * Added topology pre and post apply callbacks.
    * Added topology offerer modify callback.
    * Added topology offerer configure callback.

* Had to rework the unit tests because I changed how SDP topologies are
merged.  Replaced several unit tests with new negotiation tests.

Change-Id: If07fe6d79fbdce33968a9401d41d908385043a06
2017-06-20 18:15:52 -05:00
Richard Mudgett 4797a8bb81 stream: Ignore declined streams for some topology calls.
* Made ast_format_cap_from_stream_topology() not include any formats from
declined streams.

* Made ast_stream_topology_get_first_stream_by_type() ignore declined
streams to return the first active stream of the type.

* Updated unit tests to check these changes have the expected effect.

Change-Id: Iabbc6a3e8edf263a25fd3056c3c614407c7897df
2017-06-15 09:42:15 -05:00
Richard Mudgett 06265b8c8a stream: Add ast_stream_topology_del_stream() and unit test.
Change-Id: If07e3c716a2e3ff85ae905c17572ea6ec3cdc1f9
2017-06-15 09:42:15 -05:00
Mark Michelson 2da869408a Add primitive SFU support to bridge_softmix.
This sets up the "plumbing" in bridge_softmix to
be able to accommodate Asterisk asking as an SFU
(selective forwarding unit) for conferences.

The way this works is that whenever a channel enters or leaves a
conference, all participants in the bridge get sent a stream topology
change request. The topologies consist of the channels' original
topology, along with video destination streams corresponding to each
participants' source video streams. So for instance, if Alice, Bob, and
Carol are in the conference, and each supplies one video stream, then
the topologies for each would look like so:

Alice:
Audio,
Source video(Alice),
Destination Video(Bob),
Destination video (Carol)

Bob:
Audio,
Source video(Bob)
Destination Video(Alice),
Destination video (Carol)

Carol:
Audio,
Source video(Carol)
Destination Video(Alice),
Destination video (Bob)

This way, video that arrives from a source video stream can then be
copied out to the destination video streams on the other participants'
channels.

Once the bridge gets told that a topology on a channel has changed, the
bridge constructs a map in order to get the video frames routed to the
proper destination streams. This is done using the bridge channel's
stream_map.

This change is bare-bones with regards to SFU support. Some key features
are missing at this point:

* Stream limits. This commit makes no effort to limit the number of
  streams on a specific channel. This means that if there were 50 video
  callers in a conference, bridge_softmix will happily send out topology
  change requests to every channel in the bridge, requesting 50+
  streams.

* Configuration. The plumbing has been added to bridge_softmix, but
  there has been nothing added as of yet to app_confbridge to enable SFU
  video mode.

* Testing. Some functions included here have unit tests.
  However, the functionality as a whole has only been verified by
  hand-tracing the code.

* Selectivenss. For a "selective" forwarding unit, this does not
  currently have any means of being selective.

* Features. Presumably, someone might wish to only receive video from
  specific sources. There are no external-facing functions at the moment
  that allow for users to select who they receive video from.

* Efficiency. The current scheme treats all video streams as being
  unidirectional. We could be re-using a source video stream as a
  desetnation, too. But to simplify things on this first round, I did it
  this way.

Change-Id: I7c44a829cc63acf8b596a337b2dc3c13898a6c4d
2017-05-30 10:24:01 -05:00
Richard Mudgett 56c5c51076 stream: ast_stream_clone() cannot copy the opaque user data.
ast_stream_clone() cannot copy the opaque user data stored on a stream.
We don't know how to clone the data so it isn't copied into the clone.

Change-Id: Ia51321bf38ecbfdcc53787ca77ea5fd2cabdf367
2017-05-05 18:49:19 -05:00
Kevin Harwell 7b0e3b92fd bridge_simple: Added support for streams
This patch is the first cut at adding stream support to the bridging framework.
Changes were made to the framework that allows mapping of stream topologies to
a bridge's supported media types.

The first channel to enter a bridge initially defines the media types for a
bridge (i.e. a one to one mapping is created between the bridge and the first
channel). Subsequently added channels merge their media types into the bridge's
adding to it when necessary. This allows channels with different sized
topologies to map correctly to each other according to media type. The bridge
drops any frame that does not have a matching index into a given write stream.

For now though, bridge_simple will align its two channels according to size or
first to join. Once both channels join the bridge the one with the most streams
will indicate to the other channel to update its streams to be the same as that
of the other. If both channels have the same number of streams then the first
channel to join is chosen as the stream base.

A topology change source was also added to a channel when a stream toplogy
change request is made. This allows subsystems to know whether or not they
initiated a change request. Thus avoiding potential recursive situations.

ASTERISK-26966 #close

Change-Id: I1eb5987921dd80c3cdcf52accc136393ca2d4163
2017-05-03 16:36:22 -05:00
Richard Mudgett 5c1851cbc0 stream: Make ast_stream_topology_create_from_format_cap() allow NULL cap.
Change-Id: Ie29760c49c25d7022ba2124698283181a0dd5d08
2017-04-27 19:08:05 -05:00
Joshua Colp 2b22c3c84b channel: Add ability to request an outgoing channel with stream topology.
This change extends the ast_request functionality by adding another
function and callback to create an outgoing channel with a requested
stream topology. Fallback is provided by either converting the
requested stream topology into a format capabilities structure if
the channel driver does not support streams or by converting the
requested format capabilities into a stream topology if the channel
driver does support streams.

The Dial application has also been updated to request an outgoing
channel with the stream topology of the calling channel.

ASTERISK-26959

Change-Id: Ifa9037a672ac21d42dd7125aa09816dc879a70e6
2017-04-27 10:39:46 +00:00
George Joseph 8470c2bdea RFC sdp: Initial SDP creation
* Added additional fields to ast_sdp_options.
* Re-organized ast_sdp.
* Updated field names to correspond to RFC4566 terminology.
* Created allocs/frees for SDP children.
* Created getters/setters for SDP children where appropriate.
* Added ast_sdp_create_from_state.
* Refactored res_sdp_translator_pjmedia for changes.

Change-Id: Iefbd877af7f5a4d3c74deead1bff8802661b0d48
2017-03-14 12:26:32 -06:00
Joshua Colp f58aefba5b core: Show streams in "core show channel".
The "core show channel" CLI command will now output the streams
present on the channel with their details.

ASTERISK-26811

Change-Id: I9c95b57aa09415005f0677a1949a0feb07e4987a
2017-02-22 14:32:23 +00:00
George Joseph f8f513d363 stream: Rename creates/destroys to allocs/frees
To be consistent with sdp implementation.

Change-Id: I714e300939b4188f58ca66ce9d1e84b287009500
2017-02-16 09:10:02 -06:00
George Joseph bf2f091bbb stream: Add stream topology to channel
Adds topology set and get to channel.

ASTERISK-26790

Change-Id: Ic379ea82a9486fc79dbd8c4d95c29fa3b46424f4
2017-02-14 14:09:37 -07:00
Joshua Colp 6c4657e28e stream: Add stream topology unit tests and fix uncovered bugs.
This change adds unit tests for the various API calls relating
to stream topologies. This includes creation, destruction,
inspection, and manipulation.

Through this a few bugs were uncovered in the implementation:

1. Creating a topology using a format capabilities would fail as
the code considered a return value of 0 from the append stream
function to indicate an error which is incorrect.

2. Not all functions which placed a stream into a topology
set the position on the stream itself.

3. Appending a stream would cause a frack if the position
provided was the last one. This occurred because the existing
stream was queried but the index was outside of what the
vector was currently at for size.

ASTERISK-26786

Change-Id: Id5590e87c8a605deea1a89e53169a9c011d66fa0
2017-02-13 17:00:42 +00:00
George Joseph 8b72ec312b stream: Add media stream topology definition and API
This change adds the media stream topology definition and API for
accessing and using it.

Some refactoring of the stream was also done.

ASTERISK-26786

Change-Id: Ic930232d24d5ad66dcabc14e9b359e0ff8e7f568
2017-02-13 07:49:25 -07:00
Joshua Colp bab4885f1e stream: Add media stream definition and API with unit tests.
This change adds the media stream definition and API for
accessing and using it. Unit tests have also been written
which exercise aspects of the API.

ASTERISK-26773

Change-Id: I3dbe54065b55aaa51f467e1a3bafd67fb48cac87
2017-02-10 09:58:03 -07:00