ARI: Add ability to raise arbitrary User Events
[asterisk/asterisk.git] / main / rtp_engine.c
index 8a9dacf..5174b9c 100644 (file)
@@ -839,6 +839,14 @@ static int rtp_payload_type_find_format(void *obj, void *arg, int flags)
        return (type->asterisk_format && (ast_format_cmp(&type->format, format) != AST_FORMAT_CMP_NOT_EQUAL)) ? CMP_MATCH | CMP_STOP : 0;
 }
 
+static int rtp_payload_type_find_nonast_format(void *obj, void *arg, int flags)
+{
+       struct ast_rtp_payload_type *type = obj;
+       int *rtp_code = arg;
+
+       return ((!type->asterisk_format && (type->rtp_code == *rtp_code)) ? CMP_MATCH | CMP_STOP : 0);
+}
+
 int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
 {
        struct ast_rtp_payload_type *type;
@@ -848,7 +856,7 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_form
                res = type->payload;
                ao2_ref(type, -1);
                return res;
-       } else if (!asterisk_format && (type = ao2_find(codecs->payloads, &code, OBJ_NOLOCK | OBJ_KEY))) {
+       } else if (!asterisk_format && (type = ao2_callback(codecs->payloads, OBJ_NOLOCK, rtp_payload_type_find_nonast_format, (void*)&code))) {
                res = type->payload;
                ao2_ref(type, -1);
                return res;
@@ -1073,90 +1081,90 @@ void ast_rtp_instance_set_bridged(struct ast_rtp_instance *instance, struct ast_
        instance->bridged = bridged;
 }
 
-void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
+void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c_dst, struct ast_channel *c_src)
 {
-       struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
-               *vinstance0 = NULL, *vinstance1 = NULL,
-               *tinstance0 = NULL, *tinstance1 = NULL;
-       struct ast_rtp_glue *glue0, *glue1;
-       enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
-       enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
-       struct ast_format_cap *cap0 = ast_format_cap_alloc_nolock();
-       struct ast_format_cap *cap1 = ast_format_cap_alloc_nolock();
+       struct ast_rtp_instance *instance_dst = NULL, *instance_src = NULL,
+               *vinstance_dst = NULL, *vinstance_src = NULL,
+               *tinstance_dst = NULL, *tinstance_src = NULL;
+       struct ast_rtp_glue *glue_dst, *glue_src;
+       enum ast_rtp_glue_result audio_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID;
+       enum ast_rtp_glue_result audio_glue_src_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_src_res = AST_RTP_GLUE_RESULT_FORBID;
+       struct ast_format_cap *cap_dst = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+       struct ast_format_cap *cap_src = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
 
        /* Lock both channels so we can look for the glue that binds them together */
-       ast_channel_lock_both(c0, c1);
+       ast_channel_lock_both(c_dst, c_src);
 
-       if (!cap1 || !cap0) {
+       if (!cap_src || !cap_dst) {
                goto done;
        }
 
        /* Grab glue that binds each channel to something using the RTP engine */
-       if (!(glue0 = ast_rtp_instance_get_glue(ast_channel_tech(c0)->type)) || !(glue1 = ast_rtp_instance_get_glue(ast_channel_tech(c1)->type))) {
-               ast_debug(1, "Can't find native functions for channel '%s'\n", glue0 ? ast_channel_name(c1) : ast_channel_name(c0));
+       if (!(glue_dst = ast_rtp_instance_get_glue(ast_channel_tech(c_dst)->type)) || !(glue_src = ast_rtp_instance_get_glue(ast_channel_tech(c_src)->type))) {
+               ast_debug(1, "Can't find native functions for channel '%s'\n", glue_dst ? ast_channel_name(c_src) : ast_channel_name(c_dst));
                goto done;
        }
 
-       audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
-       video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
+       audio_glue_dst_res = glue_dst->get_rtp_info(c_dst, &instance_dst);
+       video_glue_dst_res = glue_dst->get_vrtp_info ? glue_dst->get_vrtp_info(c_dst, &vinstance_dst) : AST_RTP_GLUE_RESULT_FORBID;
 
-       audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
-       video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
+       audio_glue_src_res = glue_src->get_rtp_info(c_src, &instance_src);
+       video_glue_src_res = glue_src->get_vrtp_info ? glue_src->get_vrtp_info(c_src, &vinstance_src) : AST_RTP_GLUE_RESULT_FORBID;
 
        /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
-       if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
-               audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
+       if (video_glue_dst_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue_dst_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue_dst_res != AST_RTP_GLUE_RESULT_REMOTE)) {
+               audio_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID;
        }
-       if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
-               audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
+       if (video_glue_src_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue_src_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue_src_res != AST_RTP_GLUE_RESULT_REMOTE)) {
+               audio_glue_src_res = AST_RTP_GLUE_RESULT_FORBID;
        }
-       if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec) {
-               glue0->get_codec(c0, cap0);
+       if (audio_glue_dst_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue_dst_res == AST_RTP_GLUE_RESULT_FORBID || video_glue_dst_res == AST_RTP_GLUE_RESULT_REMOTE) && glue_dst->get_codec) {
+               glue_dst->get_codec(c_dst, cap_dst);
        }
-       if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec) {
-               glue1->get_codec(c1, cap1);
+       if (audio_glue_src_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue_src_res == AST_RTP_GLUE_RESULT_FORBID || video_glue_src_res == AST_RTP_GLUE_RESULT_REMOTE) && glue_src->get_codec) {
+               glue_src->get_codec(c_src, cap_src);
        }
 
        /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
-       if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
+       if (audio_glue_dst_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue_src_res != AST_RTP_GLUE_RESULT_REMOTE) {
                goto done;
        }
 
        /* Make sure we have matching codecs */
-       if (!ast_format_cap_has_joint(cap0, cap1)) {
+       if (!ast_format_cap_has_joint(cap_dst, cap_src)) {
                goto done;
        }
 
-       ast_rtp_codecs_payloads_copy(&instance0->codecs, &instance1->codecs, instance1);
+       ast_rtp_codecs_payloads_copy(&instance_src->codecs, &instance_dst->codecs, instance_dst);
 
-       if (vinstance0 && vinstance1) {
-               ast_rtp_codecs_payloads_copy(&vinstance0->codecs, &vinstance1->codecs, vinstance1);
+       if (vinstance_dst && vinstance_src) {
+               ast_rtp_codecs_payloads_copy(&vinstance_src->codecs, &vinstance_dst->codecs, vinstance_dst);
        }
-       if (tinstance0 && tinstance1) {
-               ast_rtp_codecs_payloads_copy(&tinstance0->codecs, &tinstance1->codecs, tinstance1);
+       if (tinstance_dst && tinstance_src) {
+               ast_rtp_codecs_payloads_copy(&tinstance_src->codecs, &tinstance_dst->codecs, tinstance_dst);
        }
 
-       if (glue0->update_peer(c0, instance1, vinstance1, tinstance1, cap1, 0)) {
+       if (glue_dst->update_peer(c_dst, instance_src, vinstance_src, tinstance_src, cap_src, 0)) {
                ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n",
-                       ast_channel_name(c0), ast_channel_name(c1));
+                       ast_channel_name(c_dst), ast_channel_name(c_src));
        } else {
                ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n",
-                       ast_channel_name(c0), ast_channel_name(c1));
+                       ast_channel_name(c_dst), ast_channel_name(c_src));
        }
 
 done:
-       ast_channel_unlock(c0);
-       ast_channel_unlock(c1);
+       ast_channel_unlock(c_dst);
+       ast_channel_unlock(c_src);
 
-       ast_format_cap_destroy(cap0);
-       ast_format_cap_destroy(cap1);
+       ast_format_cap_destroy(cap_dst);
+       ast_format_cap_destroy(cap_src);
 
-       unref_instance_cond(&instance0);
-       unref_instance_cond(&instance1);
-       unref_instance_cond(&vinstance0);
-       unref_instance_cond(&vinstance1);
-       unref_instance_cond(&tinstance0);
-       unref_instance_cond(&tinstance1);
+       unref_instance_cond(&instance_dst);
+       unref_instance_cond(&instance_src);
+       unref_instance_cond(&vinstance_dst);
+       unref_instance_cond(&vinstance_src);
+       unref_instance_cond(&tinstance_dst);
+       unref_instance_cond(&tinstance_src);
 }
 
 int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
@@ -1167,8 +1175,8 @@ int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1
        struct ast_rtp_glue *glue0, *glue1;
        enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
        enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
-       struct ast_format_cap *cap0 = ast_format_cap_alloc_nolock();
-       struct ast_format_cap *cap1 = ast_format_cap_alloc_nolock();
+       struct ast_format_cap *cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
+       struct ast_format_cap *cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
 
        /* If there is no second channel just immediately bail out, we are of no use in that scenario */
        if (!c1 || !cap1 || !cap0) {
@@ -1280,8 +1288,8 @@ char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_r
 
        /* Now actually fill the buffer with the good information */
        if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
-               snprintf(buf, size, "ssrc=%i;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
-                        stats.local_ssrc, stats.remote_ssrc, stats.rxploss, stats.txjitter, stats.rxcount, stats.rxjitter, stats.txcount, stats.txploss, stats.rtt);
+               snprintf(buf, size, "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
+                        stats.local_ssrc, stats.remote_ssrc, stats.rxploss, stats.rxjitter, stats.rxcount, stats.txjitter, stats.txcount, stats.txploss, stats.rtt);
        } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
                snprintf(buf, size, "minrxjitter=%f;maxrxjitter=%f;avgrxjitter=%f;stdevrxjitter=%f;reported_minjitter=%f;reported_maxjitter=%f;reported_avgjitter=%f;reported_stdevjitter=%f;",
                         stats.local_minjitter, stats.local_maxjitter, stats.local_normdevjitter, sqrt(stats.local_stdevjitter), stats.remote_minjitter, stats.remote_maxjitter, stats.remote_normdevjitter, sqrt(stats.remote_stdevjitter));
@@ -1297,36 +1305,64 @@ char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_r
 
 void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance)
 {
-       char quality_buf[AST_MAX_USER_FIELD], *quality;
-       RAII_VAR(struct ast_channel *, bridge, ast_channel_bridge_peer(chan), ast_channel_cleanup);
+       char quality_buf[AST_MAX_USER_FIELD];
+       char *quality;
+       struct ast_channel *bridge = ast_channel_bridge_peer(chan);
 
-       if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
+       ast_channel_lock(chan);
+       ast_channel_stage_snapshot(chan);
+       ast_channel_unlock(chan);
+       if (bridge) {
+               ast_channel_lock(bridge);
+               ast_channel_stage_snapshot(bridge);
+               ast_channel_unlock(bridge);
+       }
+
+       quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY,
+               quality_buf, sizeof(quality_buf));
+       if (quality) {
                pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", quality);
                if (bridge) {
                        pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", quality);
                }
        }
 
-       if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)))) {
+       quality = ast_rtp_instance_get_quality(instance,
+               AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf));
+       if (quality) {
                pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", quality);
                if (bridge) {
                        pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", quality);
                }
        }
 
-       if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)))) {
+       quality = ast_rtp_instance_get_quality(instance,
+               AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf));
+       if (quality) {
                pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", quality);
                if (bridge) {
                        pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", quality);
                }
        }
 
-       if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)))) {
+       quality = ast_rtp_instance_get_quality(instance,
+               AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf));
+       if (quality) {
                pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", quality);
                if (bridge) {
                        pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", quality);
                }
        }
+
+       ast_channel_lock(chan);
+       ast_channel_stage_snapshot_done(chan);
+       ast_channel_unlock(chan);
+       if (bridge) {
+               ast_channel_lock(bridge);
+               ast_channel_stage_snapshot_done(bridge);
+               ast_channel_unlock(bridge);
+               ast_channel_unref(bridge);
+       }
 }
 
 int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, struct ast_format *format)
@@ -1357,11 +1393,15 @@ int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_in
        }
 
        glue->get_rtp_info(peer, &peer_instance);
-
-       if (!peer_instance || peer_instance->engine != instance->engine) {
+       if (!peer_instance) {
+               ast_log(LOG_ERROR, "Unable to get_rtp_info for peer type %s\n", glue->type);
+               ast_channel_unlock(peer);
+               return -1;
+       }
+       if (peer_instance->engine != instance->engine) {
+               ast_log(LOG_ERROR, "Peer engine mismatch for type %s\n", glue->type);
                ast_channel_unlock(peer);
                ao2_ref(peer_instance, -1);
-               peer_instance = NULL;
                return -1;
        }
 
@@ -1610,7 +1650,7 @@ static void add_static_payload(int map, const struct ast_format *format, int rtp
        }
 
        if (map < 0) {
-               ast_log(LOG_WARNING, "No Dynamic RTP mapping avaliable for format %s\n" ,ast_getformatname(format));
+               ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n" ,ast_getformatname(format));
                ast_rwlock_unlock(&static_RTP_PT_lock);
                return;
        }
@@ -1756,7 +1796,7 @@ static struct ast_manager_event_blob *rtcp_report_to_ami(struct stasis_message *
 
                ast_str_append(&report_string, 0, "Report%dSourceSSRC: 0x%.8x\r\n",
                                i, payload->report->report_block[i]->source_ssrc);
-               ast_str_append(&report_string, 0, "Report%dFractionLost: %u\r\n",
+               ast_str_append(&report_string, 0, "Report%dFractionLost: %d\r\n",
                                i, payload->report->report_block[i]->lost_count.fraction);
                ast_str_append(&report_string, 0, "Report%dCumulativeLost: %u\r\n",
                                i, payload->report->report_block[i]->lost_count.packets);
@@ -1780,13 +1820,14 @@ static struct ast_manager_event_blob *rtcp_report_to_ami(struct stasis_message *
                ast_str_buffer(packet_string));
 }
 
-static struct ast_json *rtcp_report_to_json(struct stasis_message *msg)
+static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
+       const struct stasis_message_sanitizer *sanitize)
 {
        struct rtcp_message_payload *payload = stasis_message_data(msg);
        RAII_VAR(struct ast_json *, json_rtcp_report, NULL, ast_json_unref);
        RAII_VAR(struct ast_json *, json_rtcp_report_blocks, NULL, ast_json_unref);
        RAII_VAR(struct ast_json *, json_rtcp_sender_info, NULL, ast_json_unref);
-       struct ast_json * json_payload;
+       RAII_VAR(struct ast_json *, json_channel, NULL, ast_json_unref);
        int i;
 
        json_rtcp_report_blocks = ast_json_array_create();
@@ -1835,11 +1876,17 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg)
                return NULL;
        }
 
-       json_payload = ast_json_pack("{s: O, s: O, s: O}",
-               "channel", payload->snapshot ? ast_channel_snapshot_to_json(payload->snapshot) : ast_json_null(),
+       if (payload->snapshot) {
+               json_channel = ast_channel_snapshot_to_json(payload->snapshot, sanitize);
+               if (!json_channel) {
+                       return NULL;
+               }
+       }
+
+       return ast_json_pack("{s: O, s: O, s: O}",
+               "channel", payload->snapshot ? json_channel : ast_json_null(),
                "rtcp_report", json_rtcp_report,
                "blob", payload->blob);
-       return json_payload;
 }
 
 static void rtp_rtcp_report_dtor(void *obj)
@@ -1868,28 +1915,22 @@ void ast_rtp_publish_rtcp_message(struct ast_rtp_instance *rtp,
                struct ast_rtp_rtcp_report *report,
                struct ast_json *blob)
 {
-       RAII_VAR(struct rtcp_message_payload *, payload,
-                       ao2_alloc(sizeof(*payload), rtcp_message_payload_dtor), ao2_cleanup);
-       RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+       RAII_VAR(struct rtcp_message_payload *, payload, NULL, ao2_cleanup);
        RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
 
+       payload = ao2_alloc(sizeof(*payload), rtcp_message_payload_dtor);
        if (!payload || !report) {
                return;
        }
 
        if (!ast_strlen_zero(rtp->channel_uniqueid)) {
-               snapshot = ast_channel_snapshot_get_latest(rtp->channel_uniqueid);
-               if (snapshot) {
-                       ao2_ref(snapshot, +1);
-               }
+               payload->snapshot = ast_channel_snapshot_get_latest(rtp->channel_uniqueid);
        }
-
        if (blob) {
+               payload->blob = blob;
                ast_json_ref(blob);
        }
-       ao2_ref(report, 1);
-       payload->snapshot = snapshot;
-       payload->blob = blob;
+       ao2_ref(report, +1);
        payload->report = report;
 
        message = stasis_message_create(message_type, payload);
@@ -1969,7 +2010,7 @@ int ast_rtp_engine_init()
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_PNG, 0), 0, "video", "PNG", 90000);
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H261, 0), 0, "video", "H261", 90000);
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H263, 0), 0, "video", "H263", 90000);
-       set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), 0, "video", "h263-1998", 90000);
+       set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H263_PLUS, 0), 0, "video", "H263-1998", 90000);
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_H264, 0), 0, "video", "H264", 90000);
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_MP4_VIDEO, 0), 0, "video", "MP4V-ES", 90000);
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_T140RED, 0), 0, "text", "RED", 1000);
@@ -1977,6 +2018,9 @@ int ast_rtp_engine_init()
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SIREN7, 0), 0, "audio", "G7221", 16000);
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SIREN14, 0), 0, "audio", "G7221", 32000);
        set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G719, 0), 0, "audio", "G719", 48000);
+       /* Opus and VP8 */
+       set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), 0,  "audio", "opus", 48000);
+       set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), 0,  "video", "VP8", 90000);
 
        /* Define the static rtp payload mappings */
        add_static_payload(0, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0);
@@ -2018,6 +2062,9 @@ int ast_rtp_engine_init()
        add_static_payload(118, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), 0); /* 16 Khz signed linear */
        add_static_payload(119, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX32, 0), 0);
        add_static_payload(121, NULL, AST_RTP_CISCO_DTMF);   /* Must be type 121 */
+       /* Opus and VP8 */
+       add_static_payload(100, ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), 0);
+       add_static_payload(107, ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), 0);
 
        return 0;
 }