diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index ae877eb6e3cb48fd0dc390d08a1af35a4d03fee3..21f5190e57e1945ed39fa2927af3749bde48b575 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -600,7 +600,7 @@ static void sfu_topologies_on_join(struct ast_bridge_channel *joiner, struct ast
 		if (participant == joiner) {
 			continue;
 		}
-		participant_topology = ast_stream_topology_clone(ast_channel_get_stream_topology(joiner->chan));
+		participant_topology = ast_stream_topology_clone(ast_channel_get_stream_topology(participant->chan));
 		if (!participant_topology) {
 			goto cleanup;
 		}
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 197cc990dbdc0abe0f8a6ca26b5926a8f566be69..55126b472f565fa0a27c47bc2db155a3e336f131 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -2029,6 +2029,26 @@ struct ast_frame *ast_read_stream(struct ast_channel *chan);
  */
 struct ast_frame *ast_read_noaudio(struct ast_channel *chan);
 
+/*!
+ * \brief Reads a frame, but does not filter to just the default streams,
+ * returning AST_FRAME_NULL frame if audio.
+ *
+ * \param chan channel to read a frame from
+ *
+ * \return Returns a frame, or NULL on error.  If it returns NULL, you
+ * best just stop reading frames and assume the channel has been
+ * disconnected.
+ *
+ * \note This function will not perform any filtering and will return
+ *       media frames from all streams on the channel. To determine which
+ *       stream a frame originated from the stream_num on it can be
+ *       examined.
+ *
+ * \note Audio is replaced with AST_FRAME_NULL to avoid
+ * transcode when the resulting audio is not necessary.
+ */
+struct ast_frame *ast_read_stream_noaudio(struct ast_channel *chan);
+
 /*!
  * \brief Write a frame to a channel
  * This function writes the given frame to the indicated channel.
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index e8ab8a898051ea18a8937a5d049e5627d28b9389..2e943000cc1001a2ac0ad3e64fc63aa71cccb9f0 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -998,21 +998,6 @@ int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, st
 		return 0;
 	}
 
-	if (ast_channel_is_multistream(bridge_channel->chan) &&
-	    (fr->frametype == AST_FRAME_IMAGE || fr->frametype == AST_FRAME_TEXT ||
-	     fr->frametype == AST_FRAME_VIDEO || fr->frametype == AST_FRAME_VOICE)) {
-		/* Media frames need to be mapped to an appropriate write stream */
-		dup->stream_num = AST_VECTOR_GET(
-			&bridge_channel->stream_map.to_bridge, fr->stream_num);
-		if (dup->stream_num == -1) {
-			ast_bridge_channel_unlock(bridge_channel);
-			bridge_frame_free(dup);
-			return 0;
-		}
-	} else {
-		dup->stream_num = -1;
-	}
-
 	AST_LIST_INSERT_TAIL(&bridge_channel->wr_queue, dup, frame_list);
 	if (ast_alertpipe_write(bridge_channel->alert_pipe)) {
 		ast_log(LOG_ERROR, "We couldn't write alert pipe for %p(%s)... something is VERY wrong\n",
@@ -2455,15 +2440,26 @@ static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel)
 	}
 
 	if (bridge_channel->features->mute) {
-		frame = ast_read_noaudio(bridge_channel->chan);
+		frame = ast_read_stream_noaudio(bridge_channel->chan);
 	} else {
-		frame = ast_read(bridge_channel->chan);
+		frame = ast_read_stream(bridge_channel->chan);
 	}
 
 	if (!frame) {
 		ast_bridge_channel_kick(bridge_channel, 0);
 		return;
 	}
+
+	if (ast_channel_is_multistream(bridge_channel->chan) &&
+	    (frame->frametype == AST_FRAME_IMAGE || frame->frametype == AST_FRAME_TEXT ||
+	     frame->frametype == AST_FRAME_VIDEO || frame->frametype == AST_FRAME_VOICE)) {
+		/* Media frames need to be mapped to an appropriate write stream */
+		frame->stream_num = AST_VECTOR_GET(
+			&bridge_channel->stream_map.to_bridge, frame->stream_num);
+	} else {
+		frame->stream_num = -1;
+	}
+
 	switch (frame->frametype) {
 	case AST_FRAME_CONTROL:
 		switch (frame->subclass.integer) {
diff --git a/main/channel.c b/main/channel.c
index 811826f1cf08a7cbe21b8cf131ddf727e7f2382a..23bb74f0823b453422bfcda1a7f31656d234af31 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -4180,6 +4180,11 @@ struct ast_frame *ast_read_noaudio(struct ast_channel *chan)
 	return __ast_read(chan, 1, 1);
 }
 
+struct ast_frame *ast_read_stream_noaudio(struct ast_channel *chan)
+{
+	return __ast_read(chan, 1, 0);
+}
+
 int ast_indicate(struct ast_channel *chan, int condition)
 {
 	return ast_indicate_data(chan, condition, NULL, 0);
diff --git a/main/core_unreal.c b/main/core_unreal.c
index 5da7408770d9aedd56049dea7179c693cb06b056..3db6a4dbdd81be41e1f7460f43acb836423a3402 100644
--- a/main/core_unreal.c
+++ b/main/core_unreal.c
@@ -323,6 +323,19 @@ int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f)
 		return -1;
 	}
 
+	/* If we are told to write a frame with a type that has no corresponding
+	 * stream on the channel then drop it.
+	 */
+	if (f->frametype == AST_FRAME_VOICE) {
+		if (!ast_channel_get_default_stream(ast, AST_MEDIA_TYPE_AUDIO)) {
+			return 0;
+		}
+	} else if (f->frametype == AST_FRAME_VIDEO) {
+		if (!ast_channel_get_default_stream(ast, AST_MEDIA_TYPE_VIDEO)) {
+			return 0;
+		}
+	}
+
 	/* Just queue for delivery to the other side */
 	ao2_ref(p, 1);
 	ao2_lock(p);