From: Seungbae Shin Date: Fri, 19 Mar 2021 05:34:21 +0000 (+0900) Subject: stream-manager: handle ramp finished task at core mainloop X-Git-Tag: submit/tizen/20210319.091643^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5e4cb76033a4a929c90b4dfb57e69c42ec3f58cc;p=platform%2Fcore%2Fmultimedia%2Fpulseaudio-modules-tizen.git stream-manager: handle ramp finished task at core mainloop Sometimes sd handle is accessed simultaneously, which may leads to memory corruption. [Version] 13.0.55 [Issue Type] Bug fix Change-Id: I214c58c1ccde292c918033aaded695f6b59324ef --- diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 6478812..51228a8 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.54 +Version: 13.0.55 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-priv.h b/src/stream-manager-priv.h index 677deff..e3d9298 100644 --- a/src/stream-manager-priv.h +++ b/src/stream-manager-priv.h @@ -233,6 +233,10 @@ typedef struct _filter_info { uint32_t n_controls; } filter_info; +typedef struct _stream_manager_msg { + pa_msgobject parent; +} stream_manager_msg; + struct _stream_manager { PA_REFCNT_DECLARE; @@ -255,6 +259,10 @@ struct _stream_manager { pa_time_event *time_event_for_unmute; pa_hashmap *filter_infos; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + stream_manager_msg *msg; + pa_hook_slot *sink_input_new_slot, *sink_input_put_slot, diff --git a/src/stream-manager.c b/src/stream-manager.c index 8232c1a..9a69289 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -129,6 +129,17 @@ static const char* notify_command_type_str[] = { #define STREAM_MAP_STREAM_AVAIL_OUT_DEVICES "avail-out-devices" #define STREAM_MAP_STREAM_AVAIL_FRAMEWORKS "avail-frameworks" +PA_DEFINE_PRIVATE_CLASS(stream_manager_msg, pa_msgobject); + +enum { + MESSAGE_RAMP_FINISHED, +}; + +struct stream_manager_param { + pa_stream_manager *m; + pa_sink_input *i; +}; + static bool is_valid_notify_command(notify_command_type_t command) { return (command < sizeof(notify_command_type_str) / sizeof(char *)); } @@ -2566,7 +2577,7 @@ static pa_hook_result_t sink_input_state_changed_cb(pa_core *core, pa_sink_input pa_assert(i); pa_assert(m); - pa_log_debug("sink-input(%p, index:%u), state(%d)", i, i->index, i->state); + pa_log_debug("sink-input(%p, index:%u, state:%d)", i, i->index, i->state); switch (i->state) { case PA_SINK_INPUT_CORKED: @@ -2615,8 +2626,7 @@ static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input * } static pa_hook_result_t sink_input_ramp_finish_cb(pa_core *core, pa_sink_input *i, pa_stream_manager *m) { - stream_ducking *sd; - void *state; + struct stream_manager_param param = { m, i }; pa_core_assert_ref(core); pa_sink_input_assert_ref(i); @@ -2625,44 +2635,9 @@ static pa_hook_result_t sink_input_ramp_finish_cb(pa_core *core, pa_sink_input * if (core->state == PA_CORE_SHUTDOWN) return PA_HOOK_OK; - pa_log_debug("sink-input(%p, index:%u)", i, i->index); - - /* Find a context id from all the ducked stream list by this stream index. - * Check the number of managed streams of the context id, if it is the last one - * then broadcast a signal with context id.*/ - PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { - if (!pa_idxset_get_by_data(sd->idx_ducking_streams, i, NULL)) { - pa_log_debug("not found matched stream(%p, index:%u) in sd(%p)", i, i->index, sd); - continue; - } - - pa_log_info("found matched stream(%p, index:%u) in sd(%p, ducking_stream_count:%d, state:%u)", - i, i->index, sd, sd->ducking_stream_count, sd->state); - - if (sd->ducking_stream_count <= 0) - continue; - - /* Remove trigger when unducked */ - if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) - pa_idxset_remove_by_data(sd->idx_ducking_streams, (void *)i, NULL); - - /* Send signal when all streams are ducked. - * Note that the condition of increasing count value below is located in - * handle_activate_ducking() of DBus handler. */ - if (--sd->ducking_stream_count == 0) { - if (sd->state == STREAM_DUCKING_STATE_DUCKING) { - sd->state = STREAM_DUCKING_STATE_DUCKED; - } else if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) { - sd->state = STREAM_DUCKING_STATE_UNDUCKED; - } else { - pa_log_warn("sd->state(%d), already ducked or unducked, skip sending signal", sd->state); - continue; - } - - pa_log_info("send signal for ramp finished - sd(%p, state:%u)", sd, sd->state); - send_ducking_state_changed_signal(pa_dbus_connection_get(m->dbus_conn), sd->trigger_index, is_stream_ducked(sd)); - } - } + pa_log_info("sink-input(%p, index:%u)", i, i->index); + pa_asyncmsgq_send(m->thread_mq.outq, PA_MSGOBJECT(m->msg), MESSAGE_RAMP_FINISHED, ¶m, 0, NULL); + pa_log_info("sink-input(%p, index:%u) : pa_asyncmsgq_send() done", i, i->index); return PA_HOOK_OK; } @@ -3765,6 +3740,70 @@ const char* pa_stream_manager_get_volume_type(pa_stream_manager *m, stream_type_ return s->volume_types[stream_type == STREAM_SINK_INPUT ? STREAM_DIRECTION_OUT : STREAM_DIRECTION_IN]; } +static int stream_manager_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct stream_manager_param* param = (struct stream_manager_param*)data; + pa_stream_manager *m; + pa_sink_input *i; + stream_ducking *sd; + void *state; + + pa_assert(param); + + m = param->m; + i = param->i; + + pa_log_info("code(%d), sink-input(%p, index:%u, state:%d)", code, i, i->index, i->state); + + if (param->m->core->state == PA_CORE_SHUTDOWN) + return 0; + + switch (code) { + case MESSAGE_RAMP_FINISHED: + /* Find a context id from all the ducked stream list by this stream index. + * Check the number of managed streams of the context id, if it is the last one + * then broadcast a signal with context id.*/ + PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { + if (!pa_idxset_get_by_data(sd->idx_ducking_streams, i, NULL)) { + pa_log_debug("not found matched stream(%p, index:%u) in sd(%p)", i, i->index, sd); + continue; + } + + pa_log_info("found matched stream(%p, index:%u) in sd(%p, ducking_stream_count:%d, state:%u)", + i, i->index, sd, sd->ducking_stream_count, sd->state); + + if (sd->ducking_stream_count <= 0) + continue; + + /* Remove trigger when unducked */ + if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) + pa_idxset_remove_by_data(sd->idx_ducking_streams, (void *)i, NULL); + + /* Send signal when all streams are ducked. + * Note that the condition of increasing count value below is located in + * handle_activate_ducking() of DBus handler. */ + if (--sd->ducking_stream_count == 0) { + if (sd->state == STREAM_DUCKING_STATE_DUCKING) { + sd->state = STREAM_DUCKING_STATE_DUCKED; + } else if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) { + sd->state = STREAM_DUCKING_STATE_UNDUCKED; + } else { + pa_log_warn("sd->state(%d), already ducked or unducked, skip sending signal", sd->state); + continue; + } + + pa_log_info("send signal for ramp finished - sd(%p, state:%u)", sd, sd->state); + send_ducking_state_changed_signal(pa_dbus_connection_get(m->dbus_conn), sd->trigger_index, is_stream_ducked(sd)); + } + } + break; + + default: + pa_assert_not_reached(); + } + + return 0; +} + pa_stream_manager* pa_stream_manager_get(pa_core *c) { pa_stream_manager *m; @@ -3779,6 +3818,14 @@ pa_stream_manager* pa_stream_manager_get(pa_core *c) { PA_REFCNT_INIT(m); m->core = c; + m->rtpoll = pa_rtpoll_new(); + if (pa_thread_mq_init(&m->thread_mq, m->core->mainloop, m->rtpoll) < 0) { + pa_log("pa_thread_mq_init() failed."); + goto fail; + } + m->msg = pa_msgobject_new(stream_manager_msg); + m->msg->parent.process_msg = stream_manager_process_msg; + if (!(m->hal = pa_hal_interface_get(c))) goto fail; @@ -3921,6 +3968,10 @@ void pa_stream_manager_unref(pa_stream_manager *m) { if (PA_REFCNT_DEC(m) > 0) return; + pa_thread_mq_done(&m->thread_mq); + pa_rtpoll_free(m->rtpoll); + pa_xfree(m->msg); + free_hook_slots(m); if (m->comm.comm)