stream-manager: Update buffer attributes as per latency from stream-map.json 38/74338/7
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 14 Jun 2016 02:21:45 +0000 (11:21 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 15 Jun 2016 08:24:30 +0000 (17:24 +0900)
Previously, buffer attributes are got from audio HAL.
But the audio HAL is not proper place to get these information because these are
very deeply related to the buffer mechanism of each stream on pulseaudio.

[Version] 5.0.56
[Profile] Common
[Issue Type] Feature Enhancement

Change-Id: I006afb9344e7ee4601a416e98486489dc8f5bb9b

packaging/pulseaudio-modules-tizen.spec
src/hal-interface.c
src/hal-interface.h
src/module-tizenaudio-sink.c
src/stream-manager-priv.h
src/stream-manager.c

index 9b5d88d..32abcab 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          5.0.55
+Version:          5.0.56
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 423b614..658a78d 100644 (file)
@@ -67,7 +67,6 @@ pa_hal_interface* pa_hal_interface_get(pa_core *core) {
         h->intf.update_route = dlsym(h->dl_handle, "audio_update_route");
         h->intf.update_route_option = dlsym(h->dl_handle, "audio_update_route_option");
         h->intf.notify_stream_connection_changed = dlsym(h->dl_handle, "audio_notify_stream_connection_changed");
-        h->intf.get_buffer_attr = dlsym(h->dl_handle, "audio_get_buffer_attr");
         h->intf.pcm_open = dlsym(h->dl_handle, "audio_pcm_open");
         h->intf.pcm_start = dlsym(h->dl_handle, "audio_pcm_start");
         h->intf.pcm_stop = dlsym(h->dl_handle, "audio_pcm_stop");
@@ -290,27 +289,6 @@ int32_t pa_hal_interface_notify_stream_connection_changed(pa_hal_interface *h, h
     return ret;
 }
 
-int32_t pa_hal_interface_get_buffer_attribute(pa_hal_interface *h, hal_stream_info *info,
-                                            uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize) {
-    int32_t ret = 0;
-    audio_return_t hal_ret = AUDIO_RET_OK;
-
-    pa_assert(h);
-    pa_assert(info);
-
-    pa_log_info("latency:%s, rate:%u, format:%d, channels:%u",
-        info->latency, info->sample_spec->rate, info->sample_spec->format, info->sample_spec->channels);
-
-    if (AUDIO_RET_OK != (hal_ret = h->intf.get_buffer_attr(h->ah_handle, info->direction, info->latency, info->sample_spec->rate, info->sample_spec->format,
-                                                         info->sample_spec->channels, maxlength, tlength, prebuf, minreq, fragsize))) {
-        pa_log_error("get_buffer_attr returns error:0x%x", hal_ret);
-        ret = -1;
-    } else
-        pa_log_info("maxlength:%d, tlength:%d, prebuf:%d, minreq:%d, fragsize:%d", *maxlength, *tlength, *prebuf, *minreq, *fragsize);
-
-    return ret;
-}
-
 int32_t pa_hal_interface_pcm_open(pa_hal_interface *h, pcm_handle *pcm_h, io_direction_t direction, pa_sample_spec *sample_spec, uint32_t period_size, uint32_t periods) {
     int32_t ret = 0;
     audio_return_t hal_ret = AUDIO_RET_OK;
index 060b401..9741339 100644 (file)
@@ -59,7 +59,6 @@ int32_t pa_hal_interface_set_volume_mute(pa_hal_interface *h, const char *volume
 int32_t pa_hal_interface_update_route(pa_hal_interface *h, hal_route_info *info);
 int32_t pa_hal_interface_update_route_option(pa_hal_interface *h, hal_route_option *option);
 int32_t pa_hal_interface_notify_stream_connection_changed(pa_hal_interface *h, hal_stream_connection_info *info);
-int32_t pa_hal_interface_get_buffer_attribute(pa_hal_interface *h, hal_stream_info *info, uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
 int32_t pa_hal_interface_pcm_open(pa_hal_interface *h, pcm_handle *pcm_h, io_direction_t direction, pa_sample_spec *sample_spec, uint32_t period_size, uint32_t periods);
 int32_t pa_hal_interface_pcm_start(pa_hal_interface *h, pcm_handle pcm_h);
 int32_t pa_hal_interface_pcm_stop(pa_hal_interface *h, pcm_handle pcm_h);
index 5c6efd2..095f6de 100644 (file)
@@ -486,6 +486,7 @@ int pa__init(pa_module*m) {
         pa_log_error("fragment_size or fragments are invalid.");
         goto fail;
     }
+    pa_log_info("fragment_size(%u), fragments(%u)", u->frag_size, u->nfrags);
 
     pa_sink_new_data_init(&data);
     data.driver = __FILE__;
index 3c505de..b20e8d1 100644 (file)
@@ -39,15 +39,6 @@ typedef enum _stream_direction {
 #define IS_FOCUS_ACQUIRED(focus, type) \
       (type == STREAM_SINK_INPUT ? (focus & STREAM_FOCUS_ACQUIRED_PLAYBACK) : (focus & STREAM_FOCUS_ACQUIRED_CAPTURE))
 
-typedef struct _stream_info {
-    int32_t priority;
-    stream_route_type_t route_type;
-    const char *volume_types[STREAM_DIRECTION_MAX];
-    pa_idxset *idx_avail_in_devices;
-    pa_idxset *idx_avail_out_devices;
-    pa_idxset *idx_avail_frameworks;
-} stream_info;
-
 typedef struct _volume_info {
     bool is_hal_volume_type;
     struct _values {
@@ -57,6 +48,23 @@ typedef struct _volume_info {
     } values[STREAM_DIRECTION_MAX];
 } volume_info;
 
+typedef struct _latency_info {
+    int32_t maxlength;
+    int32_t tlength_ms;
+    int32_t minreq_ms;
+    int32_t prebuf_ms;
+    int32_t fragsize_ms;
+} latency_info;
+
+typedef struct _stream_info {
+    int32_t priority;
+    stream_route_type_t route_type;
+    const char *volume_types[STREAM_DIRECTION_MAX];
+    pa_idxset *idx_avail_in_devices;
+    pa_idxset *idx_avail_out_devices;
+    pa_idxset *idx_avail_frameworks;
+} stream_info;
+
 typedef struct _prior_max_priority_stream {
     pa_sink_input *sink_input;
     pa_source_output *source_output;
@@ -79,6 +87,7 @@ struct _stream_manager {
     pa_hashmap *volume_infos;
     pa_hashmap *volume_modifiers;
     pa_hashmap *stream_infos;
+    pa_hashmap *latency_infos;
     pa_hashmap *stream_parents;
     pa_hashmap *muted_streams;
     cur_max_priority_stream cur_highest_priority;
index bd9f053..f460560 100644 (file)
@@ -358,6 +358,7 @@ typedef enum _process_command_type {
     PROCESS_COMMAND_UPDATE_VOLUME,
     PROCESS_COMMAND_ADD_PARENT_ID,
     PROCESS_COMMAND_REMOVE_PARENT_ID,
+    PROCESS_COMMAND_UPDATE_BUFFER_ATTR,
 } process_command_type_t;
 
 typedef enum _notify_command_type {
@@ -377,6 +378,7 @@ const char* process_command_type_str[] = {
     "UPDATE_VOLUME",
     "ADD_PARENT_ID",
     "REMOVE_PARENT_ID",
+    "UPDATE_BUFFER_ATTR",
 };
 
 const char* notify_command_type_str[] = {
@@ -392,6 +394,13 @@ const char* notify_command_type_str[] = {
 #define STREAM_MAP_VOLUMES "volumes"
 #define STREAM_MAP_VOLUME_TYPE "type"
 #define STREAM_MAP_VOLUME_IS_FOR_HAL "is-hal-volume"
+#define STREAM_MAP_LATENCIES "latencies"
+#define STREAM_MAP_LATENCY_TYPE "type"
+#define STREAM_MAP_LATENCY_FRAGSIZE_MS "fragsize-ms"
+#define STREAM_MAP_LATENCY_TLENGTH_MS "tlength-ms"
+#define STREAM_MAP_LATENCY_MINREQ_MS "minreq-ms"
+#define STREAM_MAP_LATENCY_PREBUF_MS "prebuf-ms"
+#define STREAM_MAP_LATENCY_MAXLENGTH "maxlength"
 #define STREAM_MAP_STREAMS "streams"
 #define STREAM_MAP_STREAM_ROLE "role"
 #define STREAM_MAP_STREAM_PRIORITY "priority"
@@ -1363,33 +1372,20 @@ static void dump_stream_map(pa_stream_manager *m) {
 static int init_stream_map(pa_stream_manager *m) {
     volume_info *v;
     stream_info *s;
+    latency_info *l;
     json_object *o;
-    json_object *volume_array_o;
-    json_object *stream_array_o;
-    json_object *volume_type_o;
-    json_object *is_hal_volume_o;
-    json_object *role_o;
-    json_object *priority_o;
-    json_object *route_type_o;
-    json_object *volume_types_o;
-    json_object *avail_in_devices_o;
-    json_object *avail_out_devices_o;
-    json_object *avail_frameworks_o;
-    int num_of_volume_types = 0;
-    int num_of_stream_types = 0;
-    const char *volume_type = NULL;
+    json_object *array_o;
+    json_object *array_item_o;
+    json_object *item_o;
+    json_object *sub_array_o;
+    int array_length = 0;
+    int sub_array_length = 0;
+    const char *type = NULL;
     const char *role = NULL;
     int i = 0, j = 0;
-    int num_of_avail_in_devices;
-    int num_of_avail_out_devices;
-    int num_of_avail_frameworks;
     json_object *out_device_o;
     json_object *in_device_o;
     json_object *framework_o;
-    json_object *volume_o;
-    json_object *stream_o;
-    json_object *volume_type_in_o;
-    json_object *volume_type_out_o;
     void *state = NULL;
 
     pa_assert(m);
@@ -1400,58 +1396,113 @@ static int init_stream_map(pa_stream_manager *m) {
         return -1;
     }
 
+    /* Latencies */
+    m->latency_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+    if (json_object_object_get_ex(o, STREAM_MAP_LATENCIES, &array_o) && json_object_is_type(array_o, json_type_array)) {
+        array_length = json_object_array_length(array_o);
+        for (i = 0; i < array_length; i++) {
+            if ((array_item_o = json_object_array_get_idx(array_o, i)) && json_object_is_type(array_item_o, json_type_object)) {
+                l = pa_xmalloc0(sizeof(latency_info));
+                pa_log_debug("latency found [%d]", i);
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_LATENCY_TYPE, &item_o) && json_object_is_type(item_o, json_type_string)) {
+                    type = json_object_get_string(item_o);
+                    pa_log_debug(" - type : %s", type);
+                } else {
+                    pa_log_error("Get type failed");
+                    goto failed;
+                }
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_LATENCY_FRAGSIZE_MS, &item_o) && json_object_is_type(item_o, json_type_int)) {
+                    l->fragsize_ms = json_object_get_int(item_o);
+                    pa_log_debug(" - fragsize-ms : %d", l->fragsize_ms);
+                } else {
+                    pa_log_error("Get fragsize-ms failed");
+                    goto failed;
+                }
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_LATENCY_TLENGTH_MS, &item_o) && json_object_is_type(item_o, json_type_int)) {
+                    l->tlength_ms = json_object_get_int(item_o);
+                    pa_log_debug(" - tlength-ms : %d", l->tlength_ms);
+                } else {
+                    pa_log_error("Get tlength-ms failed");
+                    goto failed;
+                }
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_LATENCY_MINREQ_MS, &item_o) && json_object_is_type(item_o, json_type_int)) {
+                    l->minreq_ms = json_object_get_int(item_o);
+                    pa_log_debug(" - minreq-ms : %d", l->minreq_ms);
+                } else {
+                    pa_log_error("Get minreq-ms failed");
+                    goto failed;
+                }
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_LATENCY_PREBUF_MS, &item_o) && json_object_is_type(item_o, json_type_int)) {
+                    l->prebuf_ms = json_object_get_int(item_o);
+                    pa_log_debug(" - prebuf-ms : %d", l->prebuf_ms);
+                } else {
+                    pa_log_error("Get prebuf-ms failed");
+                    goto failed;
+                }
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_LATENCY_MAXLENGTH, &item_o) && json_object_is_type(item_o, json_type_int)) {
+                    l->maxlength = json_object_get_int(item_o);
+                    pa_log_debug(" - maxlength : %d", l->maxlength);
+                } else {
+                    pa_log_error("Get maxlength failed");
+                    goto failed;
+                }
+                pa_hashmap_put(m->latency_infos, (void*)type, l);
+            }
+        }
+    }
+
     /* Volumes */
     m->volume_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    if (json_object_object_get_ex(o, STREAM_MAP_VOLUMES, &volume_array_o) && json_object_is_type(volume_array_o, json_type_array)) {
-        num_of_volume_types = json_object_array_length(volume_array_o);
-        for (i = 0; i < num_of_volume_types; i++) {
-            if ((volume_o = json_object_array_get_idx(volume_array_o, i)) && json_object_is_type(volume_o, json_type_object)) {
+    if (json_object_object_get_ex(o, STREAM_MAP_VOLUMES, &array_o) && json_object_is_type(array_o, json_type_array)) {
+        array_length = json_object_array_length(array_o);
+        for (i = 0; i < array_length; i++) {
+            if ((array_item_o = json_object_array_get_idx(array_o, i)) && json_object_is_type(array_item_o, json_type_object)) {
                 v = pa_xmalloc0(sizeof(volume_info));
                 pa_log_debug("volume found [%d]", i);
-                if (json_object_object_get_ex(volume_o, STREAM_MAP_VOLUME_TYPE, &volume_type_o) && json_object_is_type(volume_type_o, json_type_string)) {
-                    volume_type = json_object_get_string(volume_type_o);
-                    pa_log_debug(" - type : %s", volume_type);
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_VOLUME_TYPE, &item_o) && json_object_is_type(item_o, json_type_string)) {
+                    type = json_object_get_string(item_o);
+                    pa_log_debug(" - type : %s", type);
                 } else {
                     pa_log_error("Get volume type failed");
                     goto failed;
                 }
-                if (json_object_object_get_ex(volume_o, STREAM_MAP_VOLUME_IS_FOR_HAL, &is_hal_volume_o) && json_object_is_type(is_hal_volume_o, json_type_int)) {
-                    v->is_hal_volume_type = (bool)json_object_get_int(is_hal_volume_o);
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_VOLUME_IS_FOR_HAL, &item_o) && json_object_is_type(item_o, json_type_int)) {
+                    v->is_hal_volume_type = (bool)json_object_get_int(item_o);
                     pa_log_debug(" - is-hal-volume : %d", v->is_hal_volume_type);
                 } else {
                     pa_log_error("Get is-hal-volume failed");
                     goto failed;
                 }
-                pa_hashmap_put(m->volume_infos, (void*)volume_type, v);
+                pa_hashmap_put(m->volume_infos, (void*)type, v);
             }
         }
     }
 
     /* Streams */
     m->stream_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    if (json_object_object_get_ex(o, STREAM_MAP_STREAMS, &stream_array_o) && json_object_is_type(stream_array_o, json_type_array)) {
-        num_of_stream_types = json_object_array_length(stream_array_o);
-        for (i = 0; i < num_of_stream_types; i++) {
+    if (json_object_object_get_ex(o, STREAM_MAP_STREAMS, &array_o) && json_object_is_type(array_o, json_type_array)) {
+        array_length = json_object_array_length(array_o);
+        for (i = 0; i < array_length; i++) {
 
-            if ((stream_o = json_object_array_get_idx(stream_array_o, i)) && json_object_is_type(stream_o, json_type_object)) {
+            if ((array_item_o = json_object_array_get_idx(array_o, i)) && json_object_is_type(array_item_o, json_type_object)) {
                 s = pa_xmalloc0(sizeof(stream_info));
                 pa_log_debug("stream found [%d]", i);
-                if (json_object_object_get_ex(stream_o, STREAM_MAP_STREAM_ROLE, &role_o) && json_object_is_type(role_o, json_type_string)) {
-                    role = json_object_get_string(role_o);
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_STREAM_ROLE, &item_o) && json_object_is_type(item_o, json_type_string)) {
+                    role = json_object_get_string(item_o);
                     pa_log_debug(" - role : %s", role);
                 } else {
                     pa_log_error("Get stream role failed");
                     goto failed;
                 }
-                if (json_object_object_get_ex(stream_o, STREAM_MAP_STREAM_PRIORITY, &priority_o) && json_object_is_type(priority_o, json_type_int)) {
-                    s->priority = json_object_get_int(priority_o);
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_STREAM_PRIORITY, &item_o) && json_object_is_type(item_o, json_type_int)) {
+                    s->priority = json_object_get_int(item_o);
                     pa_log_debug(" - priority : %d", s->priority);
                 } else {
                     pa_log_error("Get stream priority failed");
                     goto failed;
                 }
-                if (json_object_object_get_ex(stream_o, STREAM_MAP_STREAM_ROUTE_TYPE, &route_type_o) && json_object_is_type(route_type_o, json_type_string)) {
-                    if (convert_route_type(&(s->route_type), json_object_get_string(route_type_o))) {
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_STREAM_ROUTE_TYPE, &item_o) && json_object_is_type(item_o, json_type_string)) {
+                    if (convert_route_type(&(s->route_type), json_object_get_string(item_o))) {
                         pa_log_error("convert stream route-type failed");
                         goto failed;
                     }
@@ -1460,15 +1511,15 @@ static int init_stream_map(pa_stream_manager *m) {
                     pa_log_error("Get stream route-type failed");
                     goto failed;
                 }
-                if (json_object_object_get_ex(stream_o, STREAM_MAP_STREAM_VOLUME_TYPES, &volume_types_o) && json_object_is_type(volume_types_o, json_type_object)) {
-                    if (json_object_object_get_ex(volume_types_o, STREAM_MAP_STREAM_VOLUME_TYPE_IN, &volume_type_in_o) && json_object_is_type(volume_type_in_o, json_type_string))
-                        s->volume_types[STREAM_DIRECTION_IN] = json_object_get_string(volume_type_in_o);
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_STREAM_VOLUME_TYPES, &sub_array_o) && json_object_is_type(sub_array_o, json_type_object)) {
+                    if (json_object_object_get_ex(sub_array_o, STREAM_MAP_STREAM_VOLUME_TYPE_IN, &item_o) && json_object_is_type(item_o, json_type_string))
+                        s->volume_types[STREAM_DIRECTION_IN] = json_object_get_string(item_o);
                     else {
                         pa_log_error("Get stream volume-type-in failed");
                         goto failed;
                     }
-                    if (json_object_object_get_ex(volume_types_o, STREAM_MAP_STREAM_VOLUME_TYPE_OUT, &volume_type_out_o) && json_object_is_type(volume_type_out_o, json_type_string))
-                        s->volume_types[STREAM_DIRECTION_OUT] = json_object_get_string(volume_type_out_o);
+                    if (json_object_object_get_ex(sub_array_o, STREAM_MAP_STREAM_VOLUME_TYPE_OUT, &item_o) && json_object_is_type(item_o, json_type_string))
+                        s->volume_types[STREAM_DIRECTION_OUT] = json_object_get_string(item_o);
                     else {
                         pa_log_error("Get stream volume-type-out failed");
                         goto failed;
@@ -1478,13 +1529,13 @@ static int init_stream_map(pa_stream_manager *m) {
                     pa_log_error("Get stream volume-types failed");
                     goto failed;
                 }
-                if (json_object_object_get_ex(stream_o, STREAM_MAP_STREAM_AVAIL_IN_DEVICES, &avail_in_devices_o) && json_object_is_type(avail_in_devices_o, json_type_array)) {
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_STREAM_AVAIL_IN_DEVICES, &sub_array_o) && json_object_is_type(sub_array_o, json_type_array)) {
                     j = 0;
                     s->idx_avail_in_devices = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-                    num_of_avail_in_devices = json_object_array_length(avail_in_devices_o);
+                    sub_array_length = json_object_array_length(sub_array_o);
                     pa_log_debug(" - avail-in-devices");
-                    for (j = 0; j < num_of_avail_in_devices; j++) {
-                        if ((in_device_o = json_object_array_get_idx(avail_in_devices_o, j)) && json_object_is_type(in_device_o, json_type_string)) {
+                    for (j = 0; j < sub_array_length; j++) {
+                        if ((in_device_o = json_object_array_get_idx(sub_array_o, j)) && json_object_is_type(in_device_o, json_type_string)) {
                             pa_idxset_put(s->idx_avail_in_devices, (void*)json_object_get_string(in_device_o), NULL);
                             pa_log_debug("      device[%d] : %s", j, json_object_get_string(in_device_o));
                            }
@@ -1493,13 +1544,13 @@ static int init_stream_map(pa_stream_manager *m) {
                     pa_log_error("Get stream avail-in-devices failed");
                     goto failed;
                 }
-                if (json_object_object_get_ex(stream_o, STREAM_MAP_STREAM_AVAIL_OUT_DEVICES, &avail_out_devices_o) && json_object_is_type(avail_out_devices_o, json_type_array)) {
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_STREAM_AVAIL_OUT_DEVICES, &sub_array_o) && json_object_is_type(sub_array_o, json_type_array)) {
                     j = 0;
                     s->idx_avail_out_devices = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-                    num_of_avail_out_devices = json_object_array_length(avail_out_devices_o);
+                    sub_array_length = json_object_array_length(sub_array_o);
                     pa_log_debug(" - avail-out-devices");
-                    for (j = 0; j < num_of_avail_out_devices; j++) {
-                        if ((out_device_o = json_object_array_get_idx(avail_out_devices_o, j)) && json_object_is_type(out_device_o, json_type_string)) {
+                    for (j = 0; j < sub_array_length; j++) {
+                        if ((out_device_o = json_object_array_get_idx(sub_array_o, j)) && json_object_is_type(out_device_o, json_type_string)) {
                             pa_idxset_put(s->idx_avail_out_devices, (void*)json_object_get_string(out_device_o), NULL);
                             pa_log_debug("      device[%d] : %s", j, json_object_get_string(out_device_o));
                            }
@@ -1508,13 +1559,13 @@ static int init_stream_map(pa_stream_manager *m) {
                     pa_log_error("Get stream avail-out-devices failed");
                     goto failed;
                 }
-                if (json_object_object_get_ex(stream_o, STREAM_MAP_STREAM_AVAIL_FRAMEWORKS, &avail_frameworks_o) && json_object_is_type(avail_frameworks_o, json_type_array)) {
+                if (json_object_object_get_ex(array_item_o, STREAM_MAP_STREAM_AVAIL_FRAMEWORKS, &sub_array_o) && json_object_is_type(sub_array_o, json_type_array)) {
                     j = 0;
                     s->idx_avail_frameworks = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-                    num_of_avail_frameworks = json_object_array_length(avail_frameworks_o);
+                    sub_array_length = json_object_array_length(sub_array_o);
                     pa_log_debug(" - avail-frameworks");
-                    for (j = 0; j < num_of_avail_frameworks; j++) {
-                        if ((framework_o = json_object_array_get_idx(avail_frameworks_o, j)) && json_object_is_type(framework_o, json_type_string)) {
+                    for (j = 0; j < sub_array_length; j++) {
+                        if ((framework_o = json_object_array_get_idx(sub_array_o, j)) && json_object_is_type(framework_o, json_type_string)) {
                             pa_idxset_put(s->idx_avail_frameworks, (void*)json_object_get_string(framework_o), NULL);
                             pa_log_debug("      framework[%d] : %s", j, json_object_get_string(framework_o));
                            }
@@ -1554,12 +1605,19 @@ failed:
         }
         pa_hashmap_free(m->volume_infos);
     }
+    if (m->latency_infos) {
+        PA_HASHMAP_FOREACH(l, m->latency_infos, state) {
+            pa_xfree(l);
+        }
+        pa_hashmap_free(m->latency_infos);
+    }
     return -1;
 }
 
 static void deinit_stream_map(pa_stream_manager *m) {
     stream_info *s = NULL;
     volume_info *v = NULL;
+    latency_info *l = NULL;
     void *state = NULL;
 
     pa_assert(m);
@@ -1582,6 +1640,12 @@ static void deinit_stream_map(pa_stream_manager *m) {
         }
         pa_hashmap_free(m->volume_infos);
     }
+    if (m->latency_infos) {
+        PA_HASHMAP_FOREACH(l, m->latency_infos, state) {
+            pa_xfree(l);
+        }
+        pa_hashmap_free(m->latency_infos);
+    }
 
     return;
 }
@@ -1802,7 +1866,7 @@ static bool update_stream_parent_info(pa_stream_manager *m, process_command_type
 }
 
 static bool update_the_highest_priority_stream(pa_stream_manager *m, process_command_type_t command, void *mine,
-                                                    stream_type_t type, const char *role, bool is_new_data, bool *need_to_update) {
+                                               stream_type_t type, const char *role, bool is_new_data, bool *need_to_update) {
     uint32_t idx = 0;
     size_t size = 0;
     const int32_t *priority = NULL;
@@ -1999,6 +2063,85 @@ static bool update_the_highest_priority_stream(pa_stream_manager *m, process_com
     return true;
 }
 
+/* Update buffer attributes to new stream */
+static void update_buffer_attribute(pa_stream_manager *m, void *new_data, stream_type_t stream_type, bool is_new_data) {
+    pa_sample_spec *sample_spec;
+    const char *latency;
+    latency_info *li;
+    int32_t maxlength = -1;
+    /* playback only */
+    int32_t tlength = -1;
+    int32_t minreq = -1;
+    /* Note: pulseaudio recommends to set it to -1, but there's an issue related
+     * to a stream from gstreamer pulsesink which set this value to 0, so we set
+     * default value to 0 temporarily. */
+    int32_t prebuf = 0;
+    int32_t tlength_ms = -1;
+    int32_t minreq_ms = -1;
+    int32_t prebuf_ms = -1;
+    /* recording  only */
+    int32_t fragsize = -1;
+    int32_t fragsize_ms = -1;
+
+    pa_assert(m);
+    pa_assert(new_data);
+
+    if (!is_new_data) {
+        pa_log_warn("updating buffer attribute is only for new data, skip it");
+        return;
+    }
+
+    if ((latency = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(new_data, stream_type), PA_PROP_MEDIA_TIZEN_AUDIO_LATENCY)))
+        pa_log_info("audio_latency : %s", latency);
+    else {
+        pa_log_warn("failed to get audio_latency");
+        return;
+    }
+
+    if (!(li = pa_hashmap_get(m->latency_infos, latency))) {
+        pa_log_warn("not support this latency type[%s]", latency);
+        return;
+    }
+
+    maxlength = li->maxlength;
+    pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), PA_PROP_BUFFER_ATTR_MAXLENGTH, "%d", maxlength);
+
+    sample_spec = GET_STREAM_NEW_SAMPLE_SPEC_PTR(new_data, stream_type);
+    pa_log_info("*** sample_spec: format(%d), rate(%u), channels(%u)",
+                 sample_spec->format, sample_spec->rate, sample_spec->channels);
+
+    if (stream_type ==  STREAM_SINK_INPUT) {
+        tlength_ms = li->tlength_ms;
+        minreq_ms = li->minreq_ms;
+        prebuf_ms = li->prebuf_ms;
+
+        if (minreq_ms > 0)
+            minreq = pa_usec_to_bytes(minreq_ms * 1000, sample_spec);
+        if (tlength_ms > 0)
+            tlength = pa_usec_to_bytes(tlength_ms * 1000, sample_spec);
+        if (prebuf_ms >= 0)
+            prebuf = pa_usec_to_bytes(prebuf_ms * 1000, sample_spec);
+
+        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), PA_PROP_BUFFER_ATTR_TLENGTH, "%d", tlength);
+        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), PA_PROP_BUFFER_ATTR_MINREQ, "%d", minreq);
+        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), PA_PROP_BUFFER_ATTR_PREBUF, "%d", prebuf);
+
+        pa_log_info("*** maxlength:%d, tlength:%d, prebuf:%d, minreq:%d", maxlength, tlength, prebuf, minreq);
+
+    } else if (stream_type == STREAM_SOURCE_OUTPUT) {
+        fragsize_ms = li->fragsize_ms;
+
+        if (fragsize_ms > 0)
+            fragsize = pa_usec_to_bytes(fragsize_ms * 1000, sample_spec);
+
+        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), PA_PROP_BUFFER_ATTR_FRAGSIZE, "%d", fragsize);
+
+        pa_log_info("*** maxlength:%d, fragsize:%d", maxlength, fragsize);
+    }
+
+    return;
+}
+
 static void fill_device_info_to_hook_data(pa_stream_manager *m, void *hook_data, notify_command_type_t command, stream_type_t type, void *stream, bool is_new_data) {
     char *device_none = NULL;
     const char *p_idx = NULL;
@@ -2547,6 +2690,8 @@ static process_stream_result_t process_stream(pa_stream_manager *m, void *stream
                 //return PROCESS_STREAM_RESULT_STOP;
             }
         }
+    } else if (command == PROCESS_COMMAND_UPDATE_BUFFER_ATTR) {
+        update_buffer_attribute(m, stream, type, is_new_data);
     }
 
 FAILURE:
@@ -2554,43 +2699,6 @@ FAILURE:
     return result;
 }
 
-/* Set buffer attributes from HAL */
-static void set_buffer_attribute(pa_stream_manager *m, void *new_data, stream_type_t stream_type) {
-    int32_t maxlength = -1;
-    int32_t tlength = -1;
-    int32_t prebuf = -1;
-    int32_t minreq = -1;
-    int32_t fragsize = -1;
-    hal_stream_info info;
-
-    pa_assert(m);
-    pa_assert(new_data);
-
-    if (m->hal == NULL)
-        return;
-
-    if ((info.latency = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(new_data, stream_type), PA_PROP_MEDIA_TIZEN_AUDIO_LATENCY)))
-        pa_log_info("audio_latency : %s", info.latency);
-    else {
-        pa_log_warn("failed to get audio_latency");
-        return;
-    }
-    info.direction = (io_direction_t)!stream_type;
-    info.sample_spec = GET_STREAM_NEW_SAMPLE_SPEC_PTR(new_data, stream_type);
-
-    if (!pa_hal_interface_get_buffer_attribute(m->hal, &info, (uint32_t*)&maxlength, (uint32_t*)&tlength,
-                                             (uint32_t*)&prebuf, (uint32_t*)&minreq, (uint32_t*)&fragsize)) {
-        pa_log_info(" - maxlength:%d, tlength:%d, prebuf:%d, minreq:%d, fragsize:%d", maxlength, tlength, prebuf, minreq, fragsize);
-        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), "maxlength", "%d", maxlength);
-        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), "tlength",   "%d", tlength);
-        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), "prebuf",    "%d", prebuf);
-        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), "minreq",    "%d", minreq);
-        pa_proplist_setf(GET_STREAM_NEW_PROPLIST(new_data, stream_type), "fragsize",  "%d", fragsize);
-    }
-
-    return;
-}
-
 /* Remove the sink-input from muted streams */
 static void remove_sink_input_from_muted_streams(pa_stream_manager *m, pa_sink_input *i) {
     pa_idxset *streams;
@@ -2614,7 +2722,7 @@ static pa_hook_result_t sink_input_new_cb(pa_core *core, pa_sink_input_new_data
     pa_log_info("start sink_input_new_cb");
 
     process_stream(m, new_data, STREAM_SINK_INPUT, PROCESS_COMMAND_PREPARE, true);
-    set_buffer_attribute(m, new_data, STREAM_SINK_INPUT);
+    process_stream(m, new_data, STREAM_SINK_INPUT, PROCESS_COMMAND_UPDATE_BUFFER_ATTR, true);
     process_stream(m, new_data, STREAM_SINK_INPUT, PROCESS_COMMAND_UPDATE_VOLUME, true);
     process_stream(m, new_data, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, true);
 
@@ -2708,7 +2816,7 @@ static pa_hook_result_t source_output_new_cb(pa_core *core, pa_source_output_new
     process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_PREPARE, true);
     if (check_restrictions(m, new_data, STREAM_SOURCE_OUTPUT))
         return PA_HOOK_CANCEL;
-    set_buffer_attribute(m, new_data, STREAM_SOURCE_OUTPUT);
+    process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_UPDATE_BUFFER_ATTR, true);
     process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_UPDATE_VOLUME, true);
     process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, true);