diff options
author | zuul <zuul@gerrit.asterisk.org> | 2017-02-24 11:16:13 -0600 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2017-02-24 11:16:13 -0600 |
commit | 461577b23bfef78151dc56785baa796db4147b9e (patch) | |
tree | e3ba2944c7e6d516ee45308a56e63e9beb7fe4a9 /main | |
parent | 0f4b349d371141316d7237488b57d58c2276ee42 (diff) | |
parent | 6cc890b880a6d50b3236860c3ab89e26ba59a7d3 (diff) |
Merge "channel: Add support for writing to a specific stream."
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 54 | ||||
-rw-r--r-- | main/channel_internal_api.c | 9 |
2 files changed, 51 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: diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index 1934eb9a4..362bd1a3d 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -1816,6 +1816,15 @@ struct ast_stream_topology *ast_channel_set_stream_topology(struct ast_channel * return new_topology; } +struct ast_stream *ast_channel_get_default_stream(struct ast_channel *chan, + enum ast_media_type type) +{ + ast_assert(chan != NULL); + ast_assert(type < AST_MEDIA_TYPE_END); + + return chan->default_streams[type]; +} + void ast_channel_internal_swap_stream_topology(struct ast_channel *chan1, struct ast_channel *chan2) { |