diff options
author | Joshua Colp <jcolp@digium.com> | 2017-02-22 11:00:57 +0000 |
---|---|---|
committer | Joshua Colp <jcolp@digium.com> | 2017-02-23 18:31:15 +0000 |
commit | 6cc890b880a6d50b3236860c3ab89e26ba59a7d3 (patch) | |
tree | 2e3c881e0f076ed443d8d47230e1597a3dbb4df5 /main/channel.c | |
parent | 911252d7b54f8ee7af30f71e26e7a26ef881d316 (diff) |
channel: Add support for writing to a specific stream.
This change adds an ast_write_stream function which allows
writing a frame to a specific media stream. It also moves
ast_write() to using this underneath by writing media
frames provided to it to the default streams of the channel.
Existing functionality (such as audiohooks, framehooks, etc)
are limited to being applied to the default stream only.
Unit tests have also been added which test the behavior of
both non-multistream and multistream channels to confirm that
the write() and write_stream() callbacks are invoked
appropriately.
ASTERISK-26793
Change-Id: I4df20d1b65bd4d787fce0b4b478e19d2dfea245c
Diffstat (limited to 'main/channel.c')
-rw-r--r-- | main/channel.c | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/main/channel.c b/main/channel.c index 1e7bc563e..183f8936f 100644 --- a/main/channel.c +++ b/main/channel.c @@ -5125,6 +5125,12 @@ static void apply_plc(struct ast_channel *chan, struct ast_frame *frame) int ast_write(struct ast_channel *chan, struct ast_frame *fr) { + return ast_write_stream(chan, -1, fr); +} + +int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *fr) +{ + struct ast_stream *stream = NULL, *default_stream = NULL; int res = -1; struct ast_frame *f = NULL; int count = 0; @@ -5139,13 +5145,28 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) } usleep(1); } + /* Stop if we're a zombie or need a soft hangup */ - if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) + if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { goto done; + } + + /* If this frame is writing an audio or video frame get the stream information */ + if (fr->frametype == AST_FRAME_VOICE || fr->frametype == AST_FRAME_VIDEO) { + /* Initially use the default stream unless an explicit stream is provided */ + stream = default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(fr->subclass.format)); + + if (stream_num >= 0) { + if (stream_num >= ast_stream_topology_get_count(ast_channel_get_stream_topology(chan))) { + goto done; + } + stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), stream_num); + } + } /* Perform the framehook write event here. After the frame enters the framehook list * there is no telling what will happen, how awesome is that!!! */ - if (!(fr = ast_framehook_list_write_event(ast_channel_framehooks(chan), fr))) { + if ((stream == default_stream) && !(fr = ast_framehook_list_write_event(ast_channel_framehooks(chan), fr))) { res = 0; goto done; } @@ -5231,17 +5252,20 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) break; case AST_FRAME_VIDEO: /* XXX Handle translation of video codecs one day XXX */ - res = (ast_channel_tech(chan)->write_video == NULL) ? 0 : - ast_channel_tech(chan)->write_video(chan, fr); + if (ast_channel_tech(chan)->write_stream) { + res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr); + } else if ((stream == default_stream) && ast_channel_tech(chan)->write_video) { + res = ast_channel_tech(chan)->write_video(chan, fr); + } else { + res = 0; + + } break; case AST_FRAME_MODEM: res = (ast_channel_tech(chan)->write == NULL) ? 0 : ast_channel_tech(chan)->write(chan, fr); break; case AST_FRAME_VOICE: - if (ast_channel_tech(chan)->write == NULL) - break; /*! \todo XXX should return 0 maybe ? */ - if (ast_opt_generic_plc && ast_format_cmp(fr->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) { apply_plc(chan, fr); } @@ -5250,7 +5274,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) * Send frame to audiohooks if present, if frametype is linear (else, later as per * previous behavior) */ - if (ast_channel_audiohooks(chan)) { + if ((stream == default_stream) && ast_channel_audiohooks(chan)) { if (ast_format_cache_is_slinear(fr->subclass.format)) { struct ast_frame *old_frame; hooked = 1; @@ -5263,7 +5287,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) } /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */ - if (ast_format_cmp(fr->subclass.format, ast_channel_rawwriteformat(chan)) == AST_FORMAT_CMP_EQUAL) { + if ((stream != default_stream) || ast_format_cmp(fr->subclass.format, ast_channel_rawwriteformat(chan)) == AST_FORMAT_CMP_EQUAL) { f = fr; } else { if (ast_format_cmp(ast_channel_writeformat(chan), fr->subclass.format) != AST_FORMAT_CMP_EQUAL) { @@ -5299,7 +5323,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) break; } - if (ast_channel_audiohooks(chan) && !hooked) { + if ((stream == default_stream) && ast_channel_audiohooks(chan) && !hooked) { struct ast_frame *prev = NULL, *new_frame, *cur, *dup; int freeoldlist = 0; @@ -5348,7 +5372,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) /* the translator on chan->writetrans may have returned multiple frames from the single frame we passed in; if so, feed each one of them to the monitor */ - if (ast_channel_monitor(chan) && ast_channel_monitor(chan)->write_stream) { + if ((stream == default_stream) && ast_channel_monitor(chan) && ast_channel_monitor(chan)->write_stream) { struct ast_frame *cur; for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) { @@ -5415,7 +5439,13 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) /* reset f so the code below doesn't attempt to free it */ f = NULL; } else { - res = ast_channel_tech(chan)->write(chan, f); + if (ast_channel_tech(chan)->write_stream) { + res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), f); + } else if ((stream == default_stream) && ast_channel_tech(chan)->write) { + res = ast_channel_tech(chan)->write(chan, f); + } else { + res = 0; + } } break; case AST_FRAME_NULL: |