diff --git a/daemon/audio_player.c b/daemon/audio_player.c index a5fba28b5..326ab743a 100644 --- a/daemon/audio_player.c +++ b/daemon/audio_player.c @@ -112,7 +112,7 @@ bool audio_player_setup(struct call_media *m, const rtp_payload_type *dst_pt, if (mp) media_player_stop(mp); else { - media_player_new(&mp, m->monologue, NULL, NULL); + media_player_new(&mp, m, NULL, NULL); ap->mp = mp; } if (!mp) @@ -170,7 +170,7 @@ void audio_player_start(struct call_media *m) { if (!mp) return; - media_player_set_media(mp, m); + media_player_set_sink(mp); if (mp->next_run) // already running? return; diff --git a/daemon/call.c b/daemon/call.c index 5538a53fd..e3e84acad 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -68,7 +68,6 @@ unsigned int call_socket_cpu_affinity = 0; static int64_t add_ongoing_calls_dur_in_interval(int64_t interval_start, int64_t interval_duration); static void __call_free(call_t *p); static void __call_cleanup(call_t *c); -static void __monologue_stop(struct call_monologue *ml); __attribute__((nonnull(1, 2, 4))) static struct media_subscription *__subscribe_medias_both_ways(struct call_media * a, struct call_media * b, bool is_offer, medias_q *); @@ -2716,8 +2715,7 @@ static void __update_init_subscribers(struct call_media *media, struct stream_pa mqtt_timer_start(&media->mqtt_timer, media->call, media); } -__attribute__((nonnull(1))) -static void update_init_subscribers(struct call_media *media, struct stream_params *sp, +void update_init_subscribers(struct call_media *media, struct stream_params *sp, sdp_ng_flags *flags, enum ng_opmode opmode) { __update_init_subscribers(media, sp, flags, opmode, ++media->call->update_iter); @@ -5186,6 +5184,8 @@ static void __call_cleanup(call_t *c) { ice_shutdown(&md->ice_agent); call_media_stop(md); t38_gateway_put(&md->t38_gateway); + media_player_put(&md->players[MP_DEFAULT]); + media_player_put(&md->players[MP_REC]); audio_player_free(md); mutex_destroy(&md->dtmf_lock); sdp_sp_clear(&md->sp); @@ -5193,9 +5193,6 @@ static void __call_cleanup(call_t *c) { for (__auto_type l = c->monologues.head; l; l = l->next) { struct call_monologue *ml = l->data; - __monologue_stop(ml); - media_player_put(&ml->players[MP_DEFAULT]); - media_player_put(&ml->players[MP_REC]); if (ml->tone_freqs) g_array_free(ml->tone_freqs, true); obj_release(ml->janus_session); @@ -6428,25 +6425,21 @@ void call_media_stop(struct call_media *m) { if (!m) return; t38_gateway_stop(m->t38_gateway); + media_player_stop(m->players[MP_DEFAULT]); + media_player_stop(m->players[MP_REC]); audio_player_stop(m); codec_handlers_stop(&m->codec_handlers_store, NULL, false); rtcp_timer_stop(&m->rtcp_timer); mqtt_timer_stop(&m->mqtt_timer); } -/** - * Stops media player of given monologue. - */ -static void __monologue_stop(struct call_monologue *ml) { - media_player_stop(ml->players[MP_DEFAULT]); - media_player_stop(ml->players[MP_REC]); -} + + /** * Stops media player and all medias of given monologue. * If asked, stops all media subscribers as well. */ static void monologue_stop(struct call_monologue *ml, bool stop_media_subscribers) { /* monologue itself */ - __monologue_stop(ml); for (unsigned int i = 0; i < ml->medias->len; i++) { call_media_stop(ml->medias->pdata[i]); @@ -6458,10 +6451,8 @@ static void monologue_stop(struct call_monologue *ml, bool stop_media_subscriber struct call_media *media = ml->medias->pdata[i]; if (!media) continue; - IQUEUE_FOREACH(&media->media_subscribers, ms) { + IQUEUE_FOREACH(&media->media_subscribers, ms) call_media_stop(ms->media); - __monologue_stop(ms->monologue); - } } } } diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 510519b10..4ff6bfb45 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -2007,8 +2007,9 @@ const char *call_play_media_ng(ng_command_ctx_t *ctx) { if (err) return err; - if (l == monologues.head && monologue->players[MP_DEFAULT]->coder.duration) - parser->dict_add_int(ctx->resp, "duration", monologue->players[MP_DEFAULT]->coder.duration); + if (l == monologues.head && monologue->audio + && monologue->audio->players[MP_DEFAULT]->coder.duration) + parser->dict_add_int(ctx->resp, "duration", monologue->audio->players[MP_DEFAULT]->coder.duration); } @@ -2034,11 +2035,15 @@ const char *call_stop_media_ng(ng_command_ctx_t *ctx) { for (__auto_type l = monologues.head; l; l = l->next) { struct call_monologue *monologue = l->data; + struct call_media *audio = monologue->audio; - if (!monologue->players[MP_DEFAULT]) + if (!audio) return "Not currently playing media"; - if (monologue->players[MP_DEFAULT]->opts.moh) + if (!audio->players[MP_DEFAULT]) + return "Not currently playing media"; + + if (audio->players[MP_DEFAULT]->opts.moh) return "Currently MoH ongoing, ignore stop media."; last_frame_pos = call_stop_media_for_ml(monologue, MP_DEFAULT); diff --git a/daemon/codec.c b/daemon/codec.c index 733788ff3..9a376cbf5 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -1507,7 +1507,7 @@ void __codec_handlers_update(struct call_media *source, struct call_media *sink, if (rtpe_config.use_audio_player == UAP_PLAY_MEDIA) { // check for implicitly enabled player - if ((a.flags && a.flags->opmode == OP_PLAY_MEDIA) || (media_player_is_active(sink_ml))) { + if ((a.flags && a.flags->opmode == OP_PLAY_MEDIA) || (media_player_is_active(sink))) { use_audio_player = true; implicit_audio_player = true; } diff --git a/daemon/media_player.c b/daemon/media_player.c index 48aaf3775..5169c4192 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -183,7 +183,6 @@ static void media_player_shutdown(struct media_player *mp) { if (mp->opts.block_egress && mp->media) MEDIA_CLEAR(mp->media, BLOCK_EGRESS); - mp->media = NULL; media_player_coder_shutdown(&mp->coder); if (mp->kernel_idx != KERNEL_IDX_NONE) @@ -232,7 +231,7 @@ static void __media_player_free(struct media_player *mp) { // call->master_lock held in W -void media_player_new(struct media_player **mpp, struct call_monologue *ml, struct ssrc_entry_call *prev_ssrc, +void media_player_new(struct media_player **mpp, struct call_media *media, struct ssrc_entry_call *prev_ssrc, media_player_opts_t *opts) { #ifdef WITH_TRANSCODING @@ -251,8 +250,8 @@ void media_player_new(struct media_player **mpp, struct call_monologue *ml, stru mp->kernel_idx = KERNEL_IDX_NONE; mp->run_func = media_player_read_packet; // default - mp->call = obj_get(ml->call); - mp->ml = ml; + mp->call = obj_get(media->call); + mp->media = media; if (prev_ssrc) mp->seq = atomic_get_na(&prev_ssrc->stats->ext_seq) + 1; else @@ -1060,7 +1059,7 @@ static int __ensure_codec_handler(struct media_player *mp, const rtp_payload_typ src_pt.channels = GET_CHANNELS(mp->coder.avstream->codecpar); src_pt.clock_rate = mp->coder.avstream->codecpar->sample_rate; - codec_init_payload_type(&src_pt, MT_AUDIO); + codec_init_payload_type(&src_pt, mp->media->type_id); if (__media_player_setup_internal(mp, &src_pt, dst_pt, codec_set)) return -1; @@ -1205,8 +1204,8 @@ static bool media_player_read_packet(struct media_player *mp) { // call->master_lock held in W -void media_player_set_media(struct media_player *mp, struct call_media *media) { - mp->media = media; +void media_player_set_sink(struct media_player *mp) { + struct call_media *media = mp->media; if (media->streams.head) { mp->sink.sink = media->streams.head->data; sink_handler_set_generic(&mp->sink); @@ -1226,26 +1225,7 @@ void media_player_set_media(struct media_player *mp, struct call_media *media) { // call->master_lock held in W // returns destination payload type, or NULL on failure static const rtp_payload_type *media_player_play_setup(struct media_player *mp) { - // find call media suitable for playback - struct call_media *media; - for (unsigned int i = 0; i < mp->ml->medias->len; i++) { - media = mp->ml->medias->pdata[i]; - if (media->type_id != MT_AUDIO) - continue; - /* moh allows inactive */ - if (!mp->opts.moh && !MEDIA_ISSET(media, SEND)) - continue; - if (media->streams.length == 0) - continue; - goto found; - } - media = NULL; -found: - if (!media) { - ilog(LOG_ERR, "No suitable SDP section for media playback"); - return NULL; - } - media_player_set_media(mp, media); + media_player_set_sink(mp); return media_player_get_dst_pt(mp); } @@ -1581,11 +1561,18 @@ static bool call_ml_stops_moh(struct call_monologue *from_ml, struct call_monolo enum ng_opmode opmode) { #ifdef WITH_TRANSCODING - if (opmode == OP_OFFER && !call_ml_sendonly_inactive(from_ml) - && (to_ml->players[MP_DEFAULT] && to_ml->players[MP_DEFAULT]->opts.moh)) - { - return true; - } + if (opmode != OP_OFFER) + return false; + if (call_ml_sendonly_inactive(from_ml)) + return false; + if (!to_ml->audio) + return false; + if (!to_ml->audio->players[MP_DEFAULT]) + return false; + if (!to_ml->audio->players[MP_DEFAULT]->opts.moh) + return false; + + return true; #endif return false; } @@ -1601,48 +1588,48 @@ static bool call_ml_stops_moh(struct call_monologue *from_ml, struct call_monolo */ static void call_ml_moh_handle_flags(struct call_monologue *from_ml, struct call_monologue *to_ml) { #ifdef WITH_TRANSCODING - /* if from_ml not given, then it's a reflected MoH, use capabilities of to_ml */ struct call_monologue *moh_ml = from_ml ? : to_ml; - if (!to_ml->players[MP_DEFAULT] || + struct call_media *audio = to_ml->audio; + if (!audio) + return; + + if (!audio->players[MP_DEFAULT] || !ML_ISSET2(moh_ml, MOH_ZEROCONN, MOH_SENDRECV)) { return; } - struct call_media * media = to_ml->players[MP_DEFAULT]->media; - if (media) { - /* check zero-connection */ - if (ML_ISSET(moh_ml, MOH_ZEROCONN)) { - struct packet_stream *ps; - __auto_type msl = media->streams.head; - while (msl) - { - ps = msl->data; - if (PS_ISSET(ps, RTP)) { /* find RTP stream, and don't touch RTCP */ - ilog(LOG_DEBUG, "Forced packet stream of '"STR_FORMAT"' (media index: '%d')" - "to zero_addr due to MoH zero-connection.", - STR_FMT(&media->monologue->tag), media->index); - PS_SET(ps, ZERO_ADDR); - goto check_next; /* stop */ - } - msl = msl->next; + /* check zero-connection */ + if (ML_ISSET(moh_ml, MOH_ZEROCONN)) { + struct packet_stream *ps; + __auto_type msl = audio->streams.head; + while (msl) + { + ps = msl->data; + if (PS_ISSET(ps, RTP)) { /* find RTP stream, and don't touch RTCP */ + ilog(LOG_DEBUG, "Forced packet stream of '"STR_FORMAT"' (media index: '%d')" + "to zero_addr due to MoH zero-connection.", + STR_FMT(&audio->monologue->tag), audio->index); + PS_SET(ps, ZERO_ADDR); + goto check_next; /* stop */ } + msl = msl->next; } + } check_next: - /* check mode sendrecv */ - if (ML_ISSET(moh_ml, MOH_SENDRECV)) { - bf_set(&media->media_flags, MEDIA_FLAG_SEND | MEDIA_FLAG_RECV); - bf_set(&media->media_flags, MEDIA_FLAG_FAKE_SENDRECV); - - if (media->media_subscriptions.head) { - __auto_type sub = media->media_subscriptions.head; - __auto_type sub_m = sub->media; - /* mark real state of originators media (no flag set - inactive, real_sendonly - sendonly) */ - if (MEDIA_ISSET(sub_m, RECV)) - bf_set(&media->media_flags, MEDIA_FLAG_REAL_SENDONLY); - } + /* check mode sendrecv */ + if (ML_ISSET(moh_ml, MOH_SENDRECV)) { + bf_set(&audio->media_flags, MEDIA_FLAG_SEND | MEDIA_FLAG_RECV); + bf_set(&audio->media_flags, MEDIA_FLAG_FAKE_SENDRECV); + + if (audio->media_subscriptions.head) { + __auto_type sub = audio->media_subscriptions.head; + __auto_type sub_m = sub->media; + /* mark real state of originators media (no flag set - inactive, real_sendonly - sendonly) */ + if (MEDIA_ISSET(sub_m, RECV)) + bf_set(&audio->media_flags, MEDIA_FLAG_REAL_SENDONLY); } } #endif @@ -1681,10 +1668,8 @@ const char *call_check_moh(struct call_monologue *from_ml, struct call_monologue /* whom to play the moh audio */ errstr = call_play_media_for_ml(to_ml, MP_DEFAULT, &opts, NULL); - if (errstr) { - to_ml->players[MP_DEFAULT]->opts.moh = 0; /* initialization failed, mark accordingly */ + if (errstr) return errstr; - } /* handle MoH related flags */ call_ml_moh_handle_flags((reflected ? NULL : from_ml), to_ml); @@ -1703,6 +1688,27 @@ const char *call_check_moh(struct call_monologue *from_ml, struct call_monologue #endif } + +static void set_monologue_media(struct call_monologue *ml, bool allow_inactive) { + ml->audio = NULL; + + for (unsigned int i = 0; i < ml->medias->len; i++) { + __auto_type m = ml->medias->pdata[i]; + if (!m) + continue; + + if (m->streams.length == 0) + continue; + + if (!ml->audio && m->type_id == MT_AUDIO) + if (allow_inactive || MEDIA_ISSET(m, SEND)) + ml->audio = m; + + if (ml->audio) + return; + } +} + const char *call_play_media_for_ml(struct call_monologue *ml, unsigned int mp_idx, media_player_opts_t *opts, sdp_ng_flags *flags) { @@ -1713,7 +1719,13 @@ const char *call_play_media_for_ml(struct call_monologue *ml, unsigned int mp_id /* this starts the audio player if needed */ update_init_monologue_subscribers(ml, OP_PLAY_MEDIA); - if (ml->players[mp_idx] && ml->players[mp_idx]->opts.moh) { + set_monologue_media(ml, opts->moh); + + struct call_media *audio = ml->audio; + if (!audio) + return "No suitable output for media playback"; + + if (audio->players[mp_idx] && audio->players[mp_idx]->opts.moh) { ilog(LOG_DEBUG, "There is already ongoing media playback for MoH. Ignore new one."); /* pretend that everything is good */ return NULL; @@ -1721,11 +1733,13 @@ const char *call_play_media_for_ml(struct call_monologue *ml, unsigned int mp_id else { /* media_player_new() now knows that audio player is in use * TODO: player options can have changed if already exists */ - media_player_new(&ml->players[mp_idx], ml, NULL, opts); + media_player_new(&audio->players[mp_idx], audio, NULL, opts); } - if (!media_player_play(ml->players[mp_idx], opts)) + if (!media_player_play(audio->players[mp_idx], opts)) { + audio->players[mp_idx]->opts.moh = 0; return "Failed to start media playback"; + } return NULL; #else @@ -1733,17 +1747,29 @@ const char *call_play_media_for_ml(struct call_monologue *ml, unsigned int mp_id #endif } -long long call_stop_media_for_ml(struct call_monologue *ml, unsigned int mp_idx) -{ + #ifdef WITH_TRANSCODING - if (!ml->players[mp_idx]) +static long long call_stop_media(struct call_media *m, unsigned int mp_idx) { + if (!m) + return 0; + if (!m->players[mp_idx]) return 0; - long long ret = media_player_stop(ml->players[mp_idx]); + + long long ret = media_player_stop(m->players[mp_idx]); /* restore to non-mixing if needed */ - codec_update_all_source_handlers(ml); - update_init_monologue_subscribers(ml, OP_STOP_MEDIA); + codec_update_media_source_handlers(m); + update_init_subscribers(m, NULL, NULL, OP_STOP_MEDIA); /* mark MoH as already not used (it can be unset now) */ - ml->players[mp_idx]->opts.moh = 0; + m->players[mp_idx]->opts.moh = 0; + return ret; +} +#endif + + +long long call_stop_media_for_ml(struct call_monologue *ml, unsigned int mp_idx) +{ +#ifdef WITH_TRANSCODING + long long ret = call_stop_media(ml->audio, mp_idx); return ret; #else return 0; @@ -2052,12 +2078,12 @@ static void media_player_run(void *ptr) { } -bool media_player_is_active(struct call_monologue *ml) { - if (!ml) +bool media_player_is_active(struct call_media *m) { + if (!m) return false; - if (!ml->players[MP_DEFAULT]) + if (!m->players[MP_DEFAULT]) return false; - if (!ml->players[MP_DEFAULT]->next_run) + if (!m->players[MP_DEFAULT]->next_run) return false; return true; } diff --git a/daemon/mqtt.c b/daemon/mqtt.c index 835c196cf..e58ff30a2 100644 --- a/daemon/mqtt.c +++ b/daemon/mqtt.c @@ -169,35 +169,6 @@ static void mqtt_monologue_stats(struct call_monologue *ml, JsonBuilder *json) { json_builder_set_member_name(json, "label"); glib_json_builder_add_str(json, &ml->label); } - -#ifdef WITH_TRANSCODING - struct media_player *mp = ml->players[MP_DEFAULT]; - if (mp) { - mutex_lock(&mp->lock); - - json_builder_set_member_name(json, "media_player"); - - json_builder_begin_object(json); - - json_builder_set_member_name(json, "duration"); - json_builder_add_int_value(json, mp->coder.duration); - json_builder_set_member_name(json, "repeat"); - json_builder_add_int_value(json, mp->opts.repeat); - json_builder_set_member_name(json, "frame_time"); - json_builder_add_int_value(json, mp->last_frame_ts); - - if (mp->ssrc_out && mp->media) { - json_builder_set_member_name(json, "SSRC"); - json_builder_begin_object(json); - mqtt_ssrc_stats(mp->ssrc_out, json, mp->media); - json_builder_end_object(json); - } - - json_builder_end_object(json); - - mutex_unlock(&mp->lock); - } -#endif } @@ -465,6 +436,35 @@ static void mqtt_media_stats(struct call_media *media, JsonBuilder *json) { mutex_unlock(&media->ssrc_hash_out.lock); +#ifdef WITH_TRANSCODING + struct media_player *mp = media->players[MP_DEFAULT]; + if (mp) { + mutex_lock(&mp->lock); + + json_builder_set_member_name(json, "media_player"); + + json_builder_begin_object(json); + + json_builder_set_member_name(json, "duration"); + json_builder_add_int_value(json, mp->coder.duration); + json_builder_set_member_name(json, "repeat"); + json_builder_add_int_value(json, mp->opts.repeat); + json_builder_set_member_name(json, "frame_time"); + json_builder_add_int_value(json, mp->last_frame_ts); + + if (mp->ssrc_out && mp->media) { + json_builder_set_member_name(json, "SSRC"); + json_builder_begin_object(json); + mqtt_ssrc_stats(mp->ssrc_out, json, mp->media); + json_builder_end_object(json); + } + + json_builder_end_object(json); + + mutex_unlock(&mp->lock); + } +#endif + mqtt_stream_stats(ps, json); } diff --git a/daemon/recording.c b/daemon/recording.c index 54731ccd1..ef4f50dbf 100644 --- a/daemon/recording.c +++ b/daemon/recording.c @@ -345,8 +345,11 @@ static void recording_update_flags(call_t *call, bool streams) { static void rec_setup_monologue(struct call_monologue *ml) { recording_setup_monologue(ml); - if (ml->players[MP_REC]) { - bool ret = media_player_start(ml->players[MP_REC]); + __auto_type audio = ml->audio; + if (!audio) + return; + if (audio->players[MP_REC]) { + bool ret = media_player_start(audio->players[MP_REC]); if (!ret) ilog(LOG_WARN, "Failed to start media player for recording announcement"); } diff --git a/daemon/sdp.c b/daemon/sdp.c index 6d423774c..35670fef9 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -3192,7 +3192,7 @@ static void sdp_out_add_other(GString *out, struct call_monologue *monologue, if (flags->loop_protect) append_attr_to_gstring(out, "rtpengine", &rtpe_instance_id, flags, media->type_id); #ifdef WITH_TRANSCODING - if (monologue->players[MP_DEFAULT] && monologue->players[MP_DEFAULT]->opts.moh && rtpe_config.moh_attr_name) { + if (media->players[MP_DEFAULT] && media->players[MP_DEFAULT]->opts.moh && rtpe_config.moh_attr_name) { append_null_attr_to_gstring(out, rtpe_config.moh_attr_name, flags, media->type_id); } #endif diff --git a/daemon/t38.c b/daemon/t38.c index ac3f01c9b..9dd6c51f0 100644 --- a/daemon/t38.c +++ b/daemon/t38.c @@ -415,13 +415,13 @@ int t38_gateway_pair(struct call_media *t38_media, struct call_media *pcm_media, if (!(tg->gw = t38_gateway_init(NULL, t38_gateway_handler, tg))) goto err; - media_player_new(&tg->pcm_player, pcm_media->monologue, + media_player_new(&tg->pcm_player, pcm_media, call_get_first_ssrc(&pcm_media->ssrc_hash_out), NULL); // even though we call media_player_set_media() here, we need to call it again in // t38_gateway_start because our sink might not have any streams added here yet, // leaving the media_player setup incomplete - media_player_set_media(tg->pcm_player, pcm_media); + media_player_set_sink(tg->pcm_player); tg->pcm_player->run_func = t38_pcm_player; // set options @@ -476,7 +476,7 @@ void t38_gateway_start(struct t38_gateway *tg, str_case_value_ht codec_set) { return; // set up our player first - media_player_set_media(tg->pcm_player, tg->pcm_media); + media_player_set_sink(tg->pcm_player); if (media_player_setup(tg->pcm_player, &tg->pcm_pt, NULL, codec_set)) return; diff --git a/include/call.h b/include/call.h index bc359a87e..2a8ec04fe 100644 --- a/include/call.h +++ b/include/call.h @@ -565,6 +565,7 @@ struct call_media { struct t38_gateway *t38_gateway; struct audio_player *audio_player; struct codec_handler *t38_handler; + struct media_player *players[MP_COUNT]; unsigned int buffer_delay; @@ -632,10 +633,12 @@ struct call_monologue { GHashTable *subscribers_ht; /* for quick lookup */ medias_arr *medias; media_id_ht media_ids; - struct media_player *players[MP_COUNT]; struct session_bandwidth sdp_session_bandwidth; GString *last_out_sdp; + // for media players + struct call_media *audio; + sdp_origin sdp_orig_in; /* actual origin belonging to this monologue */ sdp_origin sdp_orig_out; /* previously used origin by other other side */ @@ -968,6 +971,7 @@ void call_media_state_machine(struct call_media *m); void call_media_unkernelize(struct call_media *media, const char *reason); void __monologue_unconfirm(struct call_monologue *monologue, const char *); void __media_unconfirm(struct call_media *media, const char *); + __attribute__((nonnull(1))) /* one monologue's state from before an offer, held as a call record snapshot */ struct call_checkpoint { @@ -982,6 +986,10 @@ void call_checkpoint_free_all(call_t *); void update_init_monologue_subscribers(struct call_monologue *ml, enum ng_opmode opmode); +__attribute__((nonnull(1))) +void update_init_subscribers(struct call_media *media, struct stream_params *sp, + sdp_ng_flags *flags, enum ng_opmode opmode); + int call_stream_address(GString *, struct packet_stream *ps, enum stream_address_format format, const struct local_intf *ifa, bool keep_unspec); diff --git a/include/media_player.h b/include/media_player.h index 2b1b07ff1..f88dbf9bf 100644 --- a/include/media_player.h +++ b/include/media_player.h @@ -66,7 +66,6 @@ struct media_player { mutex_t lock; media_player_run_func run_func; call_t *call; - struct call_monologue *ml; struct call_media *media; struct sink_handler sink; @@ -122,16 +121,16 @@ struct send_timer { #define MPO(...) (media_player_opts_t){__VA_ARGS__} -void media_player_new(struct media_player **, struct call_monologue *, +void media_player_new(struct media_player **, struct call_media *, struct ssrc_entry_call *prev_ssrc, media_player_opts_t *); bool media_player_play(struct media_player *mp, media_player_opts_t *opts); bool media_player_start(struct media_player *); long long media_player_stop(struct media_player *); -bool media_player_is_active(struct call_monologue *); +bool media_player_is_active(struct call_media *); int media_player_setup(struct media_player *mp, const rtp_payload_type *src_pt, const rtp_payload_type *dst_pt, str_case_value_ht codec_set); -void media_player_set_media(struct media_player *mp, struct call_media *media); +void media_player_set_sink(struct media_player *mp); bool media_player_pt_match(const struct media_player *mp, const rtp_payload_type *src_pt, const rtp_payload_type *dst_pt);