MT#65420 move media player into media

Change-Id: I19b52ede0eedf93fa2e8a8a63916f726e53c56ea
pull/2169/head
Richard Fuchs 3 weeks ago
parent 9066365c07
commit 56bb1920bc

@ -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;

@ -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);
}
}
}
}

@ -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);

@ -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;
}

@ -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;
}

@ -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);
}

@ -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");
}

@ -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

@ -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;

@ -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);

@ -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);

Loading…
Cancel
Save