mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
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
This commit is contained in:
@@ -77,20 +77,6 @@ enum ast_stream_state {
|
|||||||
AST_STREAM_STATE_INACTIVE,
|
AST_STREAM_STATE_INACTIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Stream data slots
|
|
||||||
*/
|
|
||||||
enum ast_stream_data_slot {
|
|
||||||
/*!
|
|
||||||
* \brief Data slot for RTP instance
|
|
||||||
*/
|
|
||||||
AST_STREAM_DATA_RTP_CODECS = 0,
|
|
||||||
/*!
|
|
||||||
* \brief Controls the size of the data pointer array
|
|
||||||
*/
|
|
||||||
AST_STREAM_DATA_SLOT_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Create a new media stream representation
|
* \brief Create a new media stream representation
|
||||||
*
|
*
|
||||||
@@ -239,32 +225,47 @@ const char *ast_stream_state2str(enum ast_stream_state state);
|
|||||||
enum ast_stream_state ast_stream_str2state(const char *str);
|
enum ast_stream_state ast_stream_str2state(const char *str);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Get the opaque stream data
|
* \brief Get a stream metadata value
|
||||||
*
|
*
|
||||||
* \param stream The media stream
|
* \param stream The media stream
|
||||||
* \param slot The data slot to retrieve
|
* \param m_key An arbitrary metadata key
|
||||||
*
|
*
|
||||||
* \retval non-NULL success
|
* \retval non-NULL metadata value
|
||||||
* \retval NULL failure
|
* \retval NULL failure or not found
|
||||||
*
|
*
|
||||||
* \since 15
|
* \since 15.5
|
||||||
*/
|
*/
|
||||||
void *ast_stream_get_data(struct ast_stream *stream, enum ast_stream_data_slot slot);
|
const char *ast_stream_get_metadata(const struct ast_stream *stream,
|
||||||
|
const char *m_key);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Set the opaque stream data
|
* \brief Get all stream metadata keys
|
||||||
*
|
*
|
||||||
* \param stream The media stream
|
* \param stream The media stream
|
||||||
* \param slot The data slot to set
|
|
||||||
* \param data Opaque data
|
|
||||||
* \param data_free_fn Callback to free data when stream is freed. May be NULL for no action.
|
|
||||||
*
|
*
|
||||||
* \return data
|
* \retval An ast_variable list of the metadata key/value pairs.
|
||||||
|
* \retval NULL if error or no variables are set.
|
||||||
*
|
*
|
||||||
* \since 15
|
* When you're finished with the list, you must call
|
||||||
|
* ast_variables_destroy(list);
|
||||||
|
*
|
||||||
|
* \since 15.5
|
||||||
*/
|
*/
|
||||||
void *ast_stream_set_data(struct ast_stream *stream, enum ast_stream_data_slot slot,
|
struct ast_variable *ast_stream_get_metadata_list(const struct ast_stream *stream);
|
||||||
void *data, ast_stream_data_free_fn data_free_fn);
|
|
||||||
|
/*!
|
||||||
|
* \brief Set a stream metadata value
|
||||||
|
*
|
||||||
|
* \param stream The media stream
|
||||||
|
* \param m_key An arbitrary metadata key
|
||||||
|
* \param value String metadata value or NULL to remove existing value
|
||||||
|
*
|
||||||
|
* \retval -1 failure
|
||||||
|
* \retval 0 success
|
||||||
|
*
|
||||||
|
* \since 15.5
|
||||||
|
*/
|
||||||
|
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Get the position of the stream in the topology
|
* \brief Get the position of the stream in the topology
|
||||||
@@ -277,6 +278,27 @@ void *ast_stream_set_data(struct ast_stream *stream, enum ast_stream_data_slot s
|
|||||||
*/
|
*/
|
||||||
int ast_stream_get_position(const struct ast_stream *stream);
|
int ast_stream_get_position(const struct ast_stream *stream);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get rtp_codecs associated with the stream
|
||||||
|
*
|
||||||
|
* \param stream The media stream
|
||||||
|
*
|
||||||
|
* \return The rtp_codecs
|
||||||
|
*
|
||||||
|
* \since 15.5
|
||||||
|
*/
|
||||||
|
struct ast_rtp_codecs *ast_stream_get_rtp_codecs(const struct ast_stream *stream);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set rtp_codecs associated with the stream
|
||||||
|
*
|
||||||
|
* \param stream The media stream
|
||||||
|
* \param rtp_codecs The rtp_codecs
|
||||||
|
*
|
||||||
|
* \since 15.5
|
||||||
|
*/
|
||||||
|
void ast_stream_set_rtp_codecs(struct ast_stream *stream, struct ast_rtp_codecs *rtp_codecs);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Create a stream topology
|
* \brief Create a stream topology
|
||||||
*
|
*
|
||||||
|
12
main/cli.c
12
main/cli.c
@@ -1614,19 +1614,29 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
|
|||||||
ast_str_append(&output, 0, " -- Streams --\n");
|
ast_str_append(&output, 0, " -- Streams --\n");
|
||||||
for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
|
for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
|
||||||
struct ast_stream *stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), stream_num);
|
struct ast_stream *stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), stream_num);
|
||||||
|
struct ast_variable *metadata = ast_stream_get_metadata_list(stream);
|
||||||
|
|
||||||
ast_str_append(&output, 0,
|
ast_str_append(&output, 0,
|
||||||
"Name: %s\n"
|
"Name: %s\n"
|
||||||
" Type: %s\n"
|
" Type: %s\n"
|
||||||
" State: %s\n"
|
" State: %s\n"
|
||||||
" Group: %d\n"
|
" Group: %d\n"
|
||||||
" Formats: %s\n",
|
" Formats: %s\n"
|
||||||
|
" Metadata:\n",
|
||||||
ast_stream_get_name(stream),
|
ast_stream_get_name(stream),
|
||||||
ast_codec_media_type2str(ast_stream_get_type(stream)),
|
ast_codec_media_type2str(ast_stream_get_type(stream)),
|
||||||
ast_stream_state2str(ast_stream_get_state(stream)),
|
ast_stream_state2str(ast_stream_get_state(stream)),
|
||||||
ast_stream_get_group(stream),
|
ast_stream_get_group(stream),
|
||||||
ast_format_cap_get_names(ast_stream_get_formats(stream), &codec_buf)
|
ast_format_cap_get_names(ast_stream_get_formats(stream), &codec_buf)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (metadata) {
|
||||||
|
struct ast_variable *v;
|
||||||
|
for(v = metadata; v; v = v->next) {
|
||||||
|
ast_str_append(&output, 0, " %s: %s\n", v->name, v->value);
|
||||||
|
}
|
||||||
|
ast_variables_destroy(metadata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_channel_unlock(chan);
|
ast_channel_unlock(chan);
|
||||||
|
@@ -848,8 +848,7 @@ static struct ast_stream *get_stream_from_m(const struct ast_sdp_a_lines *a_line
|
|||||||
ast_free(codecs);
|
ast_free(codecs);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ast_stream_set_data(stream, AST_STREAM_DATA_RTP_CODECS, codecs,
|
ast_stream_set_rtp_codecs(stream, codecs);
|
||||||
(ast_stream_data_free_fn) rtp_codecs_free);
|
|
||||||
|
|
||||||
if (!m_line->port) {
|
if (!m_line->port) {
|
||||||
/* Stream is declined. There may not be any attributes. */
|
/* Stream is declined. There may not be any attributes. */
|
||||||
|
@@ -1732,7 +1732,7 @@ static void merge_remote_stream_capabilities(
|
|||||||
case AST_MEDIA_TYPE_AUDIO:
|
case AST_MEDIA_TYPE_AUDIO:
|
||||||
case AST_MEDIA_TYPE_VIDEO:
|
case AST_MEDIA_TYPE_VIDEO:
|
||||||
ao2_bump(joint_state_stream->rtp);
|
ao2_bump(joint_state_stream->rtp);
|
||||||
codecs = ast_stream_get_data(remote_stream, AST_STREAM_DATA_RTP_CODECS);
|
codecs = ast_stream_get_rtp_codecs(remote_stream);
|
||||||
ast_assert(codecs != NULL);
|
ast_assert(codecs != NULL);
|
||||||
if (sdp_state->role == SDP_ROLE_ANSWERER) {
|
if (sdp_state->role == SDP_ROLE_ANSWERER) {
|
||||||
/*
|
/*
|
||||||
@@ -1789,7 +1789,7 @@ static int create_remote_stream_capabilities(
|
|||||||
* Setup rx payload type mapping to prefer the mapping
|
* Setup rx payload type mapping to prefer the mapping
|
||||||
* from the peer that the RFC says we SHOULD use.
|
* from the peer that the RFC says we SHOULD use.
|
||||||
*/
|
*/
|
||||||
codecs = ast_stream_get_data(remote_stream, AST_STREAM_DATA_RTP_CODECS);
|
codecs = ast_stream_get_rtp_codecs(remote_stream);
|
||||||
ast_assert(codecs != NULL);
|
ast_assert(codecs != NULL);
|
||||||
ast_rtp_codecs_payloads_xover(codecs, codecs, NULL);
|
ast_rtp_codecs_payloads_xover(codecs, codecs, NULL);
|
||||||
ast_rtp_codecs_payloads_copy(codecs,
|
ast_rtp_codecs_payloads_copy(codecs,
|
||||||
|
137
main/stream.c
137
main/stream.c
@@ -34,6 +34,15 @@
|
|||||||
#include "asterisk/strings.h"
|
#include "asterisk/strings.h"
|
||||||
#include "asterisk/format.h"
|
#include "asterisk/format.h"
|
||||||
#include "asterisk/format_cap.h"
|
#include "asterisk/format_cap.h"
|
||||||
|
#include "asterisk/vector.h"
|
||||||
|
#include "asterisk/config.h"
|
||||||
|
#include "asterisk/rtp_engine.h"
|
||||||
|
|
||||||
|
struct ast_stream_metadata_entry {
|
||||||
|
size_t length;
|
||||||
|
int value_start;
|
||||||
|
char name_value[0];
|
||||||
|
};
|
||||||
|
|
||||||
struct ast_stream {
|
struct ast_stream {
|
||||||
/*!
|
/*!
|
||||||
@@ -57,20 +66,20 @@ struct ast_stream {
|
|||||||
enum ast_stream_state state;
|
enum ast_stream_state state;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Opaque stream data
|
* \brief Stream metadata vector
|
||||||
*/
|
*/
|
||||||
void *data[AST_STREAM_DATA_SLOT_MAX];
|
struct ast_variable *metadata;
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief What to do with data when the stream is freed
|
|
||||||
*/
|
|
||||||
ast_stream_data_free_fn data_free_fn[AST_STREAM_DATA_SLOT_MAX];
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The group that the stream is part of
|
* \brief The group that the stream is part of
|
||||||
*/
|
*/
|
||||||
int group;
|
int group;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The rtp_codecs used by the stream
|
||||||
|
*/
|
||||||
|
struct ast_rtp_codecs *rtp_codecs;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Name for the stream within the context of the channel it is on
|
* \brief Name for the stream within the context of the channel it is on
|
||||||
*/
|
*/
|
||||||
@@ -105,7 +114,6 @@ struct ast_stream *ast_stream_clone(const struct ast_stream *stream, const char
|
|||||||
{
|
{
|
||||||
struct ast_stream *new_stream;
|
struct ast_stream *new_stream;
|
||||||
size_t stream_size;
|
size_t stream_size;
|
||||||
int idx;
|
|
||||||
const char *stream_name;
|
const char *stream_name;
|
||||||
|
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
@@ -126,27 +134,23 @@ struct ast_stream *ast_stream_clone(const struct ast_stream *stream, const char
|
|||||||
ao2_ref(new_stream->formats, +1);
|
ao2_ref(new_stream->formats, +1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We cannot clone the opaque data because we don't know how. */
|
new_stream->metadata = ast_stream_get_metadata_list(stream);
|
||||||
for (idx = 0; idx < AST_STREAM_DATA_SLOT_MAX; ++idx) {
|
|
||||||
new_stream->data[idx] = NULL;
|
/* rtp_codecs aren't cloned */
|
||||||
new_stream->data_free_fn[idx] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_stream;
|
return new_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_stream_free(struct ast_stream *stream)
|
void ast_stream_free(struct ast_stream *stream)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < AST_STREAM_DATA_SLOT_MAX; i++) {
|
ast_variables_destroy(stream->metadata);
|
||||||
if (stream->data_free_fn[i]) {
|
|
||||||
stream->data_free_fn[i](stream->data[i]);
|
if (stream->rtp_codecs) {
|
||||||
}
|
ast_rtp_codecs_payloads_destroy(stream->rtp_codecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ao2_cleanup(stream->formats);
|
ao2_cleanup(stream->formats);
|
||||||
@@ -238,22 +242,81 @@ enum ast_stream_state ast_stream_str2state(const char *str)
|
|||||||
return AST_STREAM_STATE_REMOVED;
|
return AST_STREAM_STATE_REMOVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ast_stream_get_data(struct ast_stream *stream, enum ast_stream_data_slot slot)
|
const char *ast_stream_get_metadata(const struct ast_stream *stream, const char *m_key)
|
||||||
{
|
{
|
||||||
ast_assert(stream != NULL);
|
struct ast_variable *v;
|
||||||
|
|
||||||
return stream->data[slot];
|
ast_assert_return(stream != NULL, NULL);
|
||||||
|
ast_assert_return(m_key != NULL, NULL);
|
||||||
|
|
||||||
|
for (v = stream->metadata; v; v = v->next) {
|
||||||
|
if (strcmp(v->name, m_key) == 0) {
|
||||||
|
return v->value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ast_stream_set_data(struct ast_stream *stream, enum ast_stream_data_slot slot,
|
return NULL;
|
||||||
void *data, ast_stream_data_free_fn data_free_fn)
|
}
|
||||||
|
|
||||||
|
struct ast_variable *ast_stream_get_metadata_list(const struct ast_stream *stream)
|
||||||
{
|
{
|
||||||
ast_assert(stream != NULL);
|
struct ast_variable *v;
|
||||||
|
struct ast_variable *vout = NULL;
|
||||||
|
|
||||||
stream->data[slot] = data;
|
ast_assert_return(stream != NULL, NULL);
|
||||||
stream->data_free_fn[slot] = data_free_fn;
|
|
||||||
|
|
||||||
return data;
|
for (v = stream->metadata; v; v = v->next) {
|
||||||
|
struct ast_variable *vt = ast_variable_new(v->name, v->value, "");
|
||||||
|
|
||||||
|
if (!vt) {
|
||||||
|
ast_variables_destroy(vout);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_variable_list_append(&vout, vt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vout;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
|
||||||
|
{
|
||||||
|
struct ast_variable *v;
|
||||||
|
struct ast_variable *prev;
|
||||||
|
|
||||||
|
ast_assert_return(stream != NULL, -1);
|
||||||
|
ast_assert_return(m_key != NULL, -1);
|
||||||
|
|
||||||
|
prev = NULL;
|
||||||
|
v = stream->metadata;
|
||||||
|
while(v) {
|
||||||
|
struct ast_variable *next = v->next;
|
||||||
|
if (strcmp(v->name, m_key) == 0) {
|
||||||
|
if (prev) {
|
||||||
|
prev->next = next;
|
||||||
|
} else {
|
||||||
|
stream->metadata = next;
|
||||||
|
}
|
||||||
|
ast_free(v);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
prev = v;
|
||||||
|
}
|
||||||
|
v = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = ast_variable_new(m_key, value, "");
|
||||||
|
if (!v) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_variable_list_append(&stream->metadata, v);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ast_stream_get_position(const struct ast_stream *stream)
|
int ast_stream_get_position(const struct ast_stream *stream)
|
||||||
@@ -263,6 +326,24 @@ int ast_stream_get_position(const struct ast_stream *stream)
|
|||||||
return stream->position;
|
return stream->position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ast_rtp_codecs *ast_stream_get_rtp_codecs(const struct ast_stream *stream)
|
||||||
|
{
|
||||||
|
ast_assert(stream != NULL);
|
||||||
|
|
||||||
|
return stream->rtp_codecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_stream_set_rtp_codecs(struct ast_stream *stream, struct ast_rtp_codecs *rtp_codecs)
|
||||||
|
{
|
||||||
|
ast_assert(stream != NULL);
|
||||||
|
|
||||||
|
if (stream->rtp_codecs) {
|
||||||
|
ast_rtp_codecs_payloads_destroy(rtp_codecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->rtp_codecs = rtp_codecs;
|
||||||
|
}
|
||||||
|
|
||||||
#define TOPOLOGY_INITIAL_STREAM_COUNT 2
|
#define TOPOLOGY_INITIAL_STREAM_COUNT 2
|
||||||
struct ast_stream_topology *ast_stream_topology_alloc(void)
|
struct ast_stream_topology *ast_stream_topology_alloc(void)
|
||||||
{
|
{
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#include "asterisk/format_cap.h"
|
#include "asterisk/format_cap.h"
|
||||||
#include "asterisk/format_cache.h"
|
#include "asterisk/format_cache.h"
|
||||||
#include "asterisk/channel.h"
|
#include "asterisk/channel.h"
|
||||||
|
#include "asterisk/uuid.h"
|
||||||
|
|
||||||
AST_TEST_DEFINE(stream_create)
|
AST_TEST_DEFINE(stream_create)
|
||||||
{
|
{
|
||||||
@@ -224,6 +225,70 @@ AST_TEST_DEFINE(stream_set_state)
|
|||||||
return AST_TEST_PASS;
|
return AST_TEST_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AST_TEST_DEFINE(stream_metadata)
|
||||||
|
{
|
||||||
|
RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
|
||||||
|
char track_label[AST_UUID_STR_LEN + 1];
|
||||||
|
const char *stream_track_label;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case TEST_INIT:
|
||||||
|
info->name = "stream_metadata";
|
||||||
|
info->category = "/main/stream/";
|
||||||
|
info->summary = "stream metadata unit test";
|
||||||
|
info->description =
|
||||||
|
"Test that metadata operations on a stream works";
|
||||||
|
return AST_TEST_NOT_RUN;
|
||||||
|
case TEST_EXECUTE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
|
||||||
|
if (!stream) {
|
||||||
|
ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
|
||||||
|
if (stream_track_label) {
|
||||||
|
ast_test_status_update(test, "New stream HAD a track label\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_uuid_generate_str(track_label, sizeof(track_label));
|
||||||
|
rc = ast_stream_set_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL", track_label);
|
||||||
|
if (rc != 0) {
|
||||||
|
ast_test_status_update(test, "Failed to add track label\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
|
||||||
|
if (!stream_track_label) {
|
||||||
|
ast_test_status_update(test, "Changed stream does not have a track label\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(stream_track_label, track_label) != 0) {
|
||||||
|
ast_test_status_update(test, "Changed stream did not return same track label\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ast_stream_set_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL", NULL);
|
||||||
|
if (rc != 0) {
|
||||||
|
ast_test_status_update(test, "Failed to remove track label\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
|
||||||
|
if (stream_track_label) {
|
||||||
|
ast_test_status_update(test, "Changed stream still had a track label after we removed it\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AST_TEST_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
AST_TEST_DEFINE(stream_topology_create)
|
AST_TEST_DEFINE(stream_topology_create)
|
||||||
{
|
{
|
||||||
RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
|
RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
|
||||||
@@ -254,6 +319,11 @@ AST_TEST_DEFINE(stream_topology_clone)
|
|||||||
RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
|
RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free);
|
||||||
RAII_VAR(struct ast_stream_topology *, cloned, NULL, ast_stream_topology_free);
|
RAII_VAR(struct ast_stream_topology *, cloned, NULL, ast_stream_topology_free);
|
||||||
struct ast_stream *audio_stream, *video_stream;
|
struct ast_stream *audio_stream, *video_stream;
|
||||||
|
char audio_track_label[AST_UUID_STR_LEN + 1];
|
||||||
|
char video_track_label[AST_UUID_STR_LEN + 1];
|
||||||
|
const char *original_track_label;
|
||||||
|
const char *cloned_track_label;
|
||||||
|
int rc;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case TEST_INIT:
|
case TEST_INIT:
|
||||||
@@ -279,6 +349,13 @@ AST_TEST_DEFINE(stream_topology_clone)
|
|||||||
return AST_TEST_FAIL;
|
return AST_TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast_uuid_generate_str(audio_track_label, sizeof(audio_track_label));
|
||||||
|
rc = ast_stream_set_metadata(audio_stream, "AST_STREAM_METADATA_TRACK_LABEL", audio_track_label);
|
||||||
|
if (rc != 0) {
|
||||||
|
ast_test_status_update(test, "Failed to add track label\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ast_stream_topology_append_stream(topology, audio_stream) == -1) {
|
if (ast_stream_topology_append_stream(topology, audio_stream) == -1) {
|
||||||
ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
|
ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
|
||||||
ast_stream_free(audio_stream);
|
ast_stream_free(audio_stream);
|
||||||
@@ -291,6 +368,13 @@ AST_TEST_DEFINE(stream_topology_clone)
|
|||||||
return AST_TEST_FAIL;
|
return AST_TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast_uuid_generate_str(video_track_label, sizeof(video_track_label));
|
||||||
|
rc = ast_stream_set_metadata(video_stream, "AST_STREAM_METADATA_TRACK_LABEL", video_track_label);
|
||||||
|
if (rc != 0) {
|
||||||
|
ast_test_status_update(test, "Failed to add track label\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ast_stream_topology_append_stream(topology, video_stream) == -1) {
|
if (ast_stream_topology_append_stream(topology, video_stream) == -1) {
|
||||||
ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
|
ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
|
||||||
ast_stream_free(video_stream);
|
ast_stream_free(video_stream);
|
||||||
@@ -313,11 +397,45 @@ AST_TEST_DEFINE(stream_topology_clone)
|
|||||||
return AST_TEST_FAIL;
|
return AST_TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
original_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(topology, 0),
|
||||||
|
"AST_STREAM_METADATA_TRACK_LABEL");
|
||||||
|
if (!original_track_label) {
|
||||||
|
ast_test_status_update(test, "Original topology stream 0 does not contain metadata\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
cloned_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(cloned, 0),
|
||||||
|
"AST_STREAM_METADATA_TRACK_LABEL");
|
||||||
|
if (!cloned_track_label) {
|
||||||
|
ast_test_status_update(test, "Cloned topology stream 0 does not contain metadata\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
if (strcmp(original_track_label, cloned_track_label) != 0) {
|
||||||
|
ast_test_status_update(test, "Cloned topology stream 0 track label was not the same as the original\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ast_stream_get_type(ast_stream_topology_get_stream(cloned, 1)) != ast_stream_get_type(ast_stream_topology_get_stream(topology, 1))) {
|
if (ast_stream_get_type(ast_stream_topology_get_stream(cloned, 1)) != ast_stream_get_type(ast_stream_topology_get_stream(topology, 1))) {
|
||||||
ast_test_status_update(test, "Cloned video stream does not contain same type as original\n");
|
ast_test_status_update(test, "Cloned video stream does not contain same type as original\n");
|
||||||
return AST_TEST_FAIL;
|
return AST_TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
original_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(topology, 1),
|
||||||
|
"AST_STREAM_METADATA_TRACK_LABEL");
|
||||||
|
if (!original_track_label) {
|
||||||
|
ast_test_status_update(test, "Original topology stream 1 does not contain metadata\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
cloned_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(cloned, 1),
|
||||||
|
"AST_STREAM_METADATA_TRACK_LABEL");
|
||||||
|
if (!cloned_track_label) {
|
||||||
|
ast_test_status_update(test, "Cloned topology stream 1 does not contain metadata\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
if (strcmp(original_track_label, cloned_track_label) != 0) {
|
||||||
|
ast_test_status_update(test, "Cloned topology stream 1 track label was not the same as the original\n");
|
||||||
|
return AST_TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
return AST_TEST_PASS;
|
return AST_TEST_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2139,6 +2257,7 @@ static int unload_module(void)
|
|||||||
AST_TEST_UNREGISTER(stream_set_type);
|
AST_TEST_UNREGISTER(stream_set_type);
|
||||||
AST_TEST_UNREGISTER(stream_set_formats);
|
AST_TEST_UNREGISTER(stream_set_formats);
|
||||||
AST_TEST_UNREGISTER(stream_set_state);
|
AST_TEST_UNREGISTER(stream_set_state);
|
||||||
|
AST_TEST_UNREGISTER(stream_metadata);
|
||||||
AST_TEST_UNREGISTER(stream_topology_create);
|
AST_TEST_UNREGISTER(stream_topology_create);
|
||||||
AST_TEST_UNREGISTER(stream_topology_clone);
|
AST_TEST_UNREGISTER(stream_topology_clone);
|
||||||
AST_TEST_UNREGISTER(stream_topology_clone);
|
AST_TEST_UNREGISTER(stream_topology_clone);
|
||||||
@@ -2169,6 +2288,7 @@ static int load_module(void)
|
|||||||
AST_TEST_REGISTER(stream_set_type);
|
AST_TEST_REGISTER(stream_set_type);
|
||||||
AST_TEST_REGISTER(stream_set_formats);
|
AST_TEST_REGISTER(stream_set_formats);
|
||||||
AST_TEST_REGISTER(stream_set_state);
|
AST_TEST_REGISTER(stream_set_state);
|
||||||
|
AST_TEST_REGISTER(stream_metadata);
|
||||||
AST_TEST_REGISTER(stream_topology_create);
|
AST_TEST_REGISTER(stream_topology_create);
|
||||||
AST_TEST_REGISTER(stream_topology_clone);
|
AST_TEST_REGISTER(stream_topology_clone);
|
||||||
AST_TEST_REGISTER(stream_topology_append_stream);
|
AST_TEST_REGISTER(stream_topology_append_stream);
|
||||||
|
Reference in New Issue
Block a user