summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/format_cap.c1
-rw-r--r--main/stream.c216
2 files changed, 212 insertions, 5 deletions
diff --git a/main/format_cap.c b/main/format_cap.c
index 1fe342b31..b0897c001 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -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);
diff --git a/main/stream.c b/main/stream.c
index fb3dbd5ce..0fabfc738 100644
--- a/main/stream.c
+++ b/main/stream.c
@@ -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;
}