summaryrefslogtreecommitdiff
path: root/main/channel.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2017-02-23 19:03:15 +0000
committerGeorge Joseph <gjoseph@digium.com>2017-02-24 10:20:33 -0600
commitc07c6714f270b7689ddd904bd52f547c19b51555 (patch)
treea517a0508a8c5f9fe1fc4554205aae051eef10e7 /main/channel.c
parent6cc890b880a6d50b3236860c3ab89e26ba59a7d3 (diff)
channel: Add ast_read_stream function for reading frames from all streams.
This change introduces an ast_read_stream function and callback in the channel technology which allows reading frames from all streams and not just the default streams. The stream number has also been added to frames. This is to allow the case where frames are queued onto the channel instead of being read directly from the driver. This change does impose a restriction on reading though: a chain of frames can only contain frames from the same stream. ASTERISK-26816 Change-Id: I5d7dc35e86694df91fd025126f6cfe0453aa38ce
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/main/channel.c b/main/channel.c
index 183f8936f..e3e9561fe 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3782,11 +3782,12 @@ static inline int calc_monitor_jump(int samples, int sample_rate, int seek_rate)
return samples;
}
-static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
+static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio, int dropnondefault)
{
struct ast_frame *f = NULL; /* the return value */
int prestate;
int cause = 0;
+ struct ast_stream *stream = NULL, *default_stream = NULL;
/* this function is very long so make sure there is only one return
* point at the end (there are only two exceptions to this).
@@ -3943,6 +3944,13 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
default:
break;
}
+ } else if (!(ast_channel_tech(chan)->properties & AST_CHAN_TP_MULTISTREAM) && (
+ f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) {
+ /* Since this channel driver does not support multistream determine the default stream this frame
+ * originated from and update the frame to include it.
+ */
+ stream = default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+ f->stream_num = ast_stream_get_position(stream);
}
} else {
ast_channel_blocker_set(chan, pthread_self());
@@ -3955,15 +3963,43 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
}
/* Clear the exception flag */
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_EXCEPTION);
- } else if (ast_channel_tech(chan) && ast_channel_tech(chan)->read)
+ } else if (ast_channel_tech(chan) && ast_channel_tech(chan)->read_stream) {
+ f = ast_channel_tech(chan)->read_stream(chan);
+
+ /* This channel driver supports multistream so the stream_num on the frame is valid, the only
+ * thing different is that we need to find the default stream so we know whether to invoke the
+ * default stream logic or not (such as transcoding).
+ */
+ if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
+ stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), f->stream_num);
+ default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+ }
+ } else if (ast_channel_tech(chan) && ast_channel_tech(chan)->read) {
f = ast_channel_tech(chan)->read(chan);
+
+ /* Since this channel driver does not support multistream determine the default stream this frame
+ * originated from and update the frame to include it.
+ */
+ if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
+ stream = default_stream = ast_channel_get_default_stream(chan, ast_format_get_type(f->subclass.format));
+ f->stream_num = ast_stream_get_position(stream);
+ }
+ }
else
ast_log(LOG_WARNING, "No read routine on channel %s\n", ast_channel_name(chan));
}
- /* Perform the framehook read event here. After the frame enters the framehook list
- * there is no telling what will happen, <insert mad scientist laugh here>!!! */
- f = ast_framehook_list_read_event(ast_channel_framehooks(chan), f);
+ if (dropnondefault && stream != default_stream) {
+ /* If the frame originates from a non-default stream and the caller can not handle other streams
+ * absord the frame and replace it with a null one instead.
+ */
+ ast_frfree(f);
+ f = &ast_null_frame;
+ } else if (stream == default_stream) {
+ /* Perform the framehook read event here. After the frame enters the framehook list
+ * there is no telling what will happen, <insert mad scientist laugh here>!!! */
+ f = ast_framehook_list_read_event(ast_channel_framehooks(chan), f);
+ }
/*
* Reset the recorded file descriptor that triggered this read so that we can
@@ -4162,6 +4198,11 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
}
break;
case AST_FRAME_VOICE:
+ /* If media was received from a non-default stream don't perform any actions, let it just go through */
+ if (stream != default_stream) {
+ break;
+ }
+
/* The EMULATE_DTMF flag must be cleared here as opposed to when the duration
* is reached , because we want to make sure we pass at least one
* voice frame through before starting the next digit, to ensure a gap
@@ -4396,12 +4437,17 @@ done:
struct ast_frame *ast_read(struct ast_channel *chan)
{
- return __ast_read(chan, 0);
+ return __ast_read(chan, 0, 1);
+}
+
+struct ast_frame *ast_read_stream(struct ast_channel *chan)
+{
+ return __ast_read(chan, 0, 0);
}
struct ast_frame *ast_read_noaudio(struct ast_channel *chan)
{
- return __ast_read(chan, 1);
+ return __ast_read(chan, 1, 1);
}
int ast_indicate(struct ast_channel *chan, int condition)