Merge "stream: Add media stream topology definition and API"

changes/42/4942/1
zuul 10 years ago committed by Gerrit Code Review
commit 09fcfb26fa

@ -33,6 +33,7 @@ enum ast_media_type {
AST_MEDIA_TYPE_VIDEO,
AST_MEDIA_TYPE_IMAGE,
AST_MEDIA_TYPE_TEXT,
AST_MEDIA_TYPE_END,
};
struct ast_module;

@ -38,6 +38,11 @@ struct ast_stream;
*/
struct ast_format_cap;
/*!
* \brief The topology of a set of streams
*/
struct ast_stream_topology;
/*!
* \brief States that a stream may be in
*/
@ -90,12 +95,25 @@ struct ast_stream *ast_stream_create(const char *name, enum ast_media_type type)
*/
void ast_stream_destroy(struct ast_stream *stream);
/*!
* \brief Create a deep clone of an existing stream
*
* \param stream The existing stream
*
* \retval non-NULL success
* \retval NULL failure
*
* \since 15
*/
struct ast_stream *ast_stream_clone(const struct ast_stream *stream);
/*!
* \brief Get the name of a stream
*
* \param stream The media stream
*
* \return The name of the stream
* \retval non-NULL success
* \retval NULL failure
*
* \since 15
*/
@ -106,7 +124,7 @@ const char *ast_stream_get_name(const struct ast_stream *stream);
*
* \param stream The media stream
*
* \return The media type of the stream
* \return The media type of the stream (AST_MEDIA_TYPE_UNKNOWN on error)
*
* \since 15
*/
@ -127,7 +145,8 @@ void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type);
*
* \param stream The media stream
*
* \return The negotiated media formats
* \retval non-NULL success
* \retval NULL failure
*
* \note The reference count is not increased
*
@ -141,6 +160,9 @@ struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream);
* \param stream The media stream
* \param caps The current negotiated formats
*
* \note The new format capabilities structure has its refcount bumped and
* any existing format capabilities structure has its refcount decremented.
*
* \since 15
*/
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps);
@ -150,7 +172,7 @@ void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *ca
*
* \param stream The media stream
*
* \return The state of the stream
* \return The state of the stream (AST_STREAM_STATE_UNKNOWN on error)
*
* \since 15
*/
@ -169,14 +191,129 @@ enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream);
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state);
/*!
* \brief Get the number of the stream
* \brief Get the position of the stream in the topology
*
* \param stream The media stream
*
* \return The number of the stream
* \return The position of the stream (-1 on error)
*
* \since 15
*/
int ast_stream_get_position(const struct ast_stream *stream);
/*!
* \brief Create a stream topology
*
* \retval non-NULL success
* \retval NULL failure
*
* \since 15
*/
struct ast_stream_topology *ast_stream_topology_create(void);
/*!
* \brief Create a deep clone of an existing stream topology
*
* \param topology The existing topology of streams
*
* \retval non-NULL success
* \retval NULL failure
*
* \since 15
*/
struct ast_stream_topology *ast_stream_topology_clone(
const struct ast_stream_topology *topology);
/*!
* \brief Destroy a stream topology
*
* \param topology The topology of streams
*
* \note All streams contained within the topology will be destroyed
*
* \since 15
*/
void ast_stream_topology_destroy(struct ast_stream_topology *topology);
/*!
* \brief Append a stream to the topology
*
* \param topology The topology of streams
* \param stream The stream to append
*
* \returns the position of the stream in the topology (-1 on error)
*
* \since 15
*/
int ast_stream_topology_append_stream(struct ast_stream_topology *topology,
struct ast_stream *stream);
/*!
* \brief Get the number of streams in a topology
*
* \param topology The topology of streams
*
* \return the number of streams (-1 on error)
*
* \since 15
*/
int ast_stream_topology_get_count(const struct ast_stream_topology *topology);
/*!
* \brief Get a specific stream from the topology
*
* \param topology The topology of streams
* \param position The topology position to get
*
* \retval non-NULL success
* \retval NULL failure
*
* \since 15
*/
struct ast_stream *ast_stream_topology_get_stream(
const struct ast_stream_topology *topology, unsigned int position);
/*!
* \brief Set a specific position in a topology
*
* \param topology The topology of streams
* \param position The topology position to set
* \param stream The stream to put in its place
*
* \retval 0 success
* \retval -1 failure
*
* \note If an existing stream exists it will be destroyed
*
* \note You can overwrite an existing position in the topology or set
* the first unused position. You can't set positions beyond that.
*
* \since 15
*/
int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
unsigned int position, struct ast_stream *stream);
/*!
* \brief A helper function that, given a format capabilities structure,
* creates a topology and separates the media types in format_cap into
* separate streams.
*
* \param caps The format capabilities structure
*
* \retval non-NULL success
* \retval NULL failure
*
* \note The format capabilities reference is NOT altered by this function
* since a new format capabilities structure is created for each media type.
*
* \note Each stream will have its name set to the corresponding media type.
* For example: "AST_MEDIA_TYPE_AUDIO".
*
* \note Each stream will be set to the sendrecv state.
*
* \since 15
*/
unsigned int ast_stream_get_num(const struct ast_stream *stream);
struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
struct ast_format_cap *cap);
#endif /* _AST_STREAM_H */

@ -268,6 +268,7 @@ int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_
{
int idx, res = 0;
/* NOTE: The streams API is dependent on the formats being in "preference" order */
for (idx = 0; (idx < AST_VECTOR_SIZE(&src->preference_order)) && !res; ++idx) {
struct format_cap_framed *framed = AST_VECTOR_GET(&src->preference_order, idx);

@ -32,6 +32,8 @@
#include "asterisk/logger.h"
#include "asterisk/stream.h"
#include "asterisk/strings.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
struct ast_stream {
/*!
@ -40,9 +42,9 @@ struct ast_stream {
enum ast_media_type type;
/*!
* \brief Unique number for the stream within the context of the channel it is on
* \brief The position of the stream in the topology
*/
unsigned int num;
unsigned int position;
/*!
* \brief Current formats negotiated on the stream
@ -60,6 +62,13 @@ struct ast_stream {
char name[0];
};
struct ast_stream_topology {
/*!
* \brief A vector of all the streams in this topology
*/
AST_VECTOR(, struct ast_stream *) streams;
};
struct ast_stream *ast_stream_create(const char *name, enum ast_media_type type)
{
struct ast_stream *stream;
@ -71,11 +80,34 @@ struct ast_stream *ast_stream_create(const char *name, enum ast_media_type type)
stream->type = type;
stream->state = AST_STREAM_STATE_INACTIVE;
strcpy(stream->name, S_OR(name, ""));
strcpy(stream->name, S_OR(name, "")); /* Safe */
return stream;
}
struct ast_stream *ast_stream_clone(const struct ast_stream *stream)
{
struct ast_stream *new_stream;
size_t stream_size;
if (!stream) {
return NULL;
}
stream_size = sizeof(*stream) + strlen(stream->name) + 1;
new_stream = ast_calloc(1, stream_size);
if (!new_stream) {
return NULL;
}
memcpy(new_stream, stream, stream_size);
if (new_stream->formats) {
ao2_ref(new_stream->formats, +1);
}
return new_stream;
}
void ast_stream_destroy(struct ast_stream *stream)
{
if (!stream) {
@ -88,41 +120,215 @@ void ast_stream_destroy(struct ast_stream *stream)
const char *ast_stream_get_name(const struct ast_stream *stream)
{
ast_assert(stream != NULL);
return stream->name;
}
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
{
ast_assert(stream != NULL);
return stream->type;
}
void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type)
{
ast_assert(stream != NULL);
stream->type = type;
}
struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream)
{
ast_assert(stream != NULL);
return stream->formats;
}
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
{
ast_assert(stream != NULL);
ao2_cleanup(stream->formats);
stream->formats = ao2_bump(caps);
}
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
{
ast_assert(stream != NULL);
return stream->state;
}
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
{
ast_assert(stream != NULL);
stream->state = state;
}
unsigned int ast_stream_get_num(const struct ast_stream *stream)
int ast_stream_get_position(const struct ast_stream *stream)
{
ast_assert(stream != NULL);
return stream->position;
}
#define TOPOLOGY_INITIAL_STREAM_COUNT 2
struct ast_stream_topology *ast_stream_topology_create(void)
{
struct ast_stream_topology *topology;
topology = ast_calloc(1, sizeof(*topology));
if (!topology) {
return NULL;
}
if (AST_VECTOR_INIT(&topology->streams, TOPOLOGY_INITIAL_STREAM_COUNT)) {
ast_free(topology);
topology = NULL;
}
return topology;
}
struct ast_stream_topology *ast_stream_topology_clone(
const struct ast_stream_topology *topology)
{
struct ast_stream_topology *new_topology;
int i;
ast_assert(topology != NULL);
new_topology = ast_stream_topology_create();
if (!new_topology) {
return NULL;
}
for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
struct ast_stream *stream =
ast_stream_clone(AST_VECTOR_GET(&topology->streams, i));
if (!stream || AST_VECTOR_APPEND(&new_topology->streams, stream)) {
ast_stream_destroy(stream);
ast_stream_topology_destroy(new_topology);
return NULL;
}
}
return new_topology;
}
void ast_stream_topology_destroy(struct ast_stream_topology *topology)
{
if (!topology) {
return;
}
AST_VECTOR_CALLBACK_VOID(&topology->streams, ast_stream_destroy);
AST_VECTOR_FREE(&topology->streams);
ast_free(topology);
}
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
{
ast_assert(topology && stream);
if (AST_VECTOR_APPEND(&topology->streams, stream)) {
return -1;
}
return AST_VECTOR_SIZE(&topology->streams) - 1;
}
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
{
ast_assert(topology != NULL);
return AST_VECTOR_SIZE(&topology->streams);
}
struct ast_stream *ast_stream_topology_get_stream(
const struct ast_stream_topology *topology, unsigned int stream_num)
{
ast_assert(topology != NULL);
return AST_VECTOR_GET(&topology->streams, stream_num);
}
int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
unsigned int position, struct ast_stream *stream)
{
return stream->num;
struct ast_stream *existing_stream;
ast_assert(topology && stream);
if (position > AST_VECTOR_SIZE(&topology->streams)) {
return -1;
}
existing_stream = AST_VECTOR_GET(&topology->streams, position);
ast_stream_destroy(existing_stream);
if (position == AST_VECTOR_SIZE(&topology->streams)) {
AST_VECTOR_APPEND(&topology->streams, stream);
return 0;
}
stream->position = position;
return AST_VECTOR_REPLACE(&topology->streams, position, stream);
}
struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
struct ast_format_cap *cap)
{
struct ast_stream_topology *topology;
enum ast_media_type type;
ast_assert(cap != NULL);
topology = ast_stream_topology_create();
if (!topology) {
return NULL;
}
for (type = AST_MEDIA_TYPE_UNKNOWN + 1; type < AST_MEDIA_TYPE_END; type++) {
struct ast_format_cap *new_cap;
struct ast_stream *stream;
if (!ast_format_cap_has_type(cap, type)) {
continue;
}
new_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!new_cap) {
ast_stream_topology_destroy(topology);
return NULL;
}
ast_format_cap_set_framing(new_cap, ast_format_cap_get_framing(cap));
if (ast_format_cap_append_from_cap(new_cap, cap, type)) {
ao2_cleanup(new_cap);
ast_stream_topology_destroy(topology);
return NULL;
}
stream = ast_stream_create(ast_codec_media_type2str(type), type);
if (!stream) {
ao2_cleanup(new_cap);
ast_stream_topology_destroy(topology);
return NULL;
}
/* We're transferring the initial ref so no bump needed */
stream->formats = new_cap;
stream->state = AST_STREAM_STATE_SENDRECV;
if (!ast_stream_topology_append_stream(topology, stream)) {
ast_stream_destroy(stream);
ast_stream_topology_destroy(topology);
return NULL;
}
}
return topology;
}

@ -87,7 +87,8 @@ static int media_type_to_fdno(enum ast_media_type media_type)
case AST_MEDIA_TYPE_VIDEO: return FD_VIDEO;
case AST_MEDIA_TYPE_TEXT:
case AST_MEDIA_TYPE_UNKNOWN:
case AST_MEDIA_TYPE_IMAGE: break;
case AST_MEDIA_TYPE_IMAGE:
case AST_MEDIA_TYPE_END: break;
}
return -1;
}

Loading…
Cancel
Save