Add code to get replay gain information after audio recording 23/170023/3
authorJeongmo Yang <jm80.yang@samsung.com>
Tue, 13 Feb 2018 02:11:54 +0000 (11:11 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Wed, 21 Feb 2018 06:21:53 +0000 (06:21 +0000)
[Version] 0.10.151
[Profile] Common
[Issue Type] Update

Change-Id: I50138e697fa923f01f868aa6ef4de14d534304f9
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
packaging/libmm-camcorder.spec
src/include/mm_camcorder.h
src/include/mm_camcorder_attribute.h
src/include/mm_camcorder_internal.h
src/mm_camcorder_attribute.c
src/mm_camcorder_audiorec.c
src/mm_camcorder_gstcommon.c

index 11f4eab..f261a46 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-camcorder
 Summary:    Camera and recorder library
-Version:    0.10.150
+Version:    0.10.151
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 1c82836..9ca12b0 100644 (file)
@@ -1299,6 +1299,16 @@ extern "C" {
  */
 #define MMCAM_GDBUS_CONNECTION                  "gdbus-connection"
 
+/**
+ * Replay gain enable
+ */
+#define MMCAM_AUDIO_REPLAY_GAIN_ENABLE          "audio-replay-gain-enable"
+
+/**
+ * Reference level for replay gain
+ */
+#define MMCAM_AUDIO_REPLAY_GAIN_REFERENCE_LEVEL "audio-replay-gain-reference-level"
+
 /*=======================================================================================
 | ENUM DEFINITIONS                                                                     |
 ========================================================================================*/
index ee6420d..c28ada7 100644 (file)
@@ -186,6 +186,8 @@ typedef enum {
        MM_CAM_DISPLAY_REUSE_HINT,
        MM_CAM_DISPLAY_REUSE_ELEMENT,
        MM_CAM_GDBUS_CONNECTION,                        /* 130 */
+       MM_CAM_AUDIO_REPLAY_GAIN_ENABLE,
+       MM_CAM_AUDIO_REPLAY_GAIN_REFERENCE_LEVEL,
        MM_CAM_ATTRIBUTE_NUM
 } MMCamcorderAttrsID;
 
@@ -388,6 +390,7 @@ bool _mmcamcorder_commit_encoded_preview_gop_interval(MMHandleType handle, int a
 bool _mmcamcorder_commit_pid_for_sound_focus(MMHandleType handle, int attr_idx, const mmf_value_t *value);
 bool _mmcamcorder_commit_sound_stream_info(MMHandleType handle, int attr_idx, const mmf_value_t *value);
 bool _mmcamcorder_commit_tag(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_audio_replay_gain(MMHandleType handle, int attr_idx, const mmf_value_t *value);
 
 
 /**
index a656e35..21bb5a1 100644 (file)
@@ -570,6 +570,7 @@ typedef enum {
        _MMCAMCORDER_AUDIOSRC_QUE,
        _MMCAMCORDER_AUDIOSRC_CONV,
        _MMCAMCORDER_AUDIOSRC_VOL,
+       _MMCAMCORDER_AUDIOSRC_RGA,      /* for replay gain analysis element */
 
        /* Pipeline element of Encodebin */
        _MMCAMCORDER_ENCSINK_BIN,
@@ -663,6 +664,16 @@ typedef struct {
 } _MMCamcorderMTSafe;
 
 /**
+ * MMCamcorder Replay gain value
+ */
+typedef struct {
+       gdouble track_peak;
+       gdouble track_gain;
+       gdouble album_peak;
+       gdouble album_gain;
+} _MMCamcorderReplayGain;
+
+/**
  * MMCamcorder Sub Context
  */
 typedef struct {
@@ -689,6 +700,9 @@ typedef struct {
        int drop_vframe;                        /**< When this value is bigger than zero and pass_first_vframe is zero, MSL will drop video frame though cam_stability count is bigger then zero. */
        int pass_first_vframe;                  /**< When this value is bigger than zero, MSL won't drop video frame though "drop_vframe" is bigger then zero. */
 
+       /* Replay gain */
+       _MMCamcorderReplayGain replay_gain;     /**< Replay gain for audio recording */
+
        /* INI information */
        unsigned int fourcc;                    /**< Get fourcc value of camera INI file */
        _MMCamcorderImageInfo *info_image;      /**< extra information for image capture */
index c6a58c3..fb85d7b 100644 (file)
@@ -37,6 +37,7 @@
 #define MMCAMCORDER_DEFAULT_CAMERA_HEIGHT       480
 #define MMCAMCORDER_DEFAULT_ENCODED_PREVIEW_BITRATE (1024*1024*10)
 #define MMCAMCORDER_DEFAULT_ENCODED_PREVIEW_GOP_INTERVAL 1000
+#define MMCAMCORDER_DEFAULT_REPLAY_GAIN_REFERENCE_LEVEL  89.0
 
 /*---------------------------------------------------------------------------------------
 |    GLOBAL VARIABLE DEFINITIONS for internal                                          |
@@ -216,7 +217,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "camera-device-name",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -261,7 +262,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "audio-volume",
                        MMF_VALUE_TYPE_DOUBLE,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)1},
+                       {.value_double = 1.0},
                        MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
                        {.double_min = 0.0},
                        {.double_max = 10.0},
@@ -383,7 +384,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "camera-recording-motion-rate",
                        MMF_VALUE_TYPE_DOUBLE,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)1},
+                       {.value_double = 1.0},
                        MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
                        {.double_min = 0.0},
                        {.double_max = _MMCAMCORDER_MAX_DOUBLE},
@@ -671,7 +672,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "display-handle",
                        MMF_VALUE_TYPE_DATA,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -838,7 +839,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "target-filename",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -882,7 +883,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "tag-image-description",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -904,7 +905,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "tag-software",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -916,7 +917,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "tag-latitude",
                        MMF_VALUE_TYPE_DOUBLE,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)0},
+                       {.value_double = 0.0},
                        MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
                        {.double_min = -360.0},
                        {.double_max = 360.0},
@@ -927,7 +928,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "tag-longitude",
                        MMF_VALUE_TYPE_DOUBLE,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)0},
+                       {.value_double = 0.0},
                        MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
                        {.double_min = -360.0},
                        {.double_max = 360.0},
@@ -938,7 +939,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "tag-altitude",
                        MMF_VALUE_TYPE_DOUBLE,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)0},
+                       {.value_double = 0.0},
                        MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
                        {.double_min = -999999.0},
                        {.double_max = 999999.0},
@@ -1093,7 +1094,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "camera-focal-length",
                        MMF_VALUE_TYPE_DOUBLE,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)0},
+                       {.value_double = 0.0},
                        MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
                        {.double_min = 0.0},
                        {.double_max = 1000.0},
@@ -1138,7 +1139,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "tag-gps-time-stamp",
                        MMF_VALUE_TYPE_DOUBLE,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)0},
+                       {.value_double = 0.0},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1149,7 +1150,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "tag-gps-date-stamp",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1160,7 +1161,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "tag-gps-processing-method",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1182,7 +1183,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "captured-screennail",
                        MMF_VALUE_TYPE_DATA,
                        MM_ATTRS_FLAG_READABLE,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1282,7 +1283,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "captured-exif-raw-data",
                        MMF_VALUE_TYPE_DATA,
                        MM_ATTRS_FLAG_READABLE,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1293,7 +1294,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "display-evas-surface-sink",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_READABLE,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1504,7 +1505,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "display-socket-path",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1526,7 +1527,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "root-directory",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1548,7 +1549,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "sound-stream-type",
                        MMF_VALUE_TYPE_STRING,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1570,7 +1571,7 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "display-reuse-element",
                        MMF_VALUE_TYPE_DATA,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
@@ -1581,11 +1582,33 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
                        "gdbus-connection",
                        MMF_VALUE_TYPE_DATA,
                        MM_ATTRS_FLAG_RW,
-                       {(void*)NULL},
+                       {NULL},
                        MM_ATTRS_VALID_TYPE_NONE,
                        {0},
                        {0},
                        NULL,
+               },
+               {
+                       MM_CAM_AUDIO_REPLAY_GAIN_ENABLE,
+                       "audio-replay-gain-enable",
+                       MMF_VALUE_TYPE_INT,
+                       MM_ATTRS_FLAG_RW,
+                       {(void*)FALSE},
+                       MM_ATTRS_VALID_TYPE_INT_RANGE,
+                       {.int_min = 0},
+                       {.int_max = 1},
+                       _mmcamcorder_commit_audio_replay_gain,
+               },
+               {
+                       MM_CAM_AUDIO_REPLAY_GAIN_REFERENCE_LEVEL,
+                       "audio-replay-gain-reference-level",
+                       MMF_VALUE_TYPE_DOUBLE,
+                       MM_ATTRS_FLAG_RW,
+                       {.value_double = MMCAMCORDER_DEFAULT_REPLAY_GAIN_REFERENCE_LEVEL},
+                       MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
+                       {.double_min = 0.0},
+                       {.double_max = 150.0},
+                       _mmcamcorder_commit_audio_replay_gain,
                }
        };
 
@@ -1630,41 +1653,46 @@ _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info)
        __mmcamcorder_set_conf_to_valid_info(handle);
 
        for (idx = 0; idx < attr_count; idx++) {
-/*             _mmcam_dbg_log("Valid type [%s:%d, %d, %d]", cam_attrs_const_info[idx].name, cam_attrs_const_info[idx].validity_type
-                       , cam_attrs_const_info[idx].validity_value1, cam_attrs_const_info[idx].validity_value2);
+               mm_cam_attr_construct_info *attr_info = &hcamcorder->cam_attrs_const_info[idx];
+
+/*
+               _mmcam_dbg_log("Valid type [%s:%d, %d, %d]",
+                       attr_info->name, attr_info->validity_type,
+                       attr_info->validity_value1, attr_info->validity_value2);
 */
-               mmf_attrs_set_valid_type(attrs, idx, hcamcorder->cam_attrs_const_info[idx].validity_type);
+               mmf_attrs_set_valid_type(attrs, idx, attr_info->validity_type);
 
-               switch (hcamcorder->cam_attrs_const_info[idx].validity_type) {
+               switch (attr_info->validity_type) {
                case MM_ATTRS_VALID_TYPE_INT_ARRAY:
-                       if (hcamcorder->cam_attrs_const_info[idx].validity_value_1.int_array &&
-                           hcamcorder->cam_attrs_const_info[idx].validity_value_2.count > 0) {
+                       if (attr_info->validity_value_1.int_array &&
+                           attr_info->validity_value_2.count > 0) {
                                mmf_attrs_set_valid_array(attrs, idx,
-                                       (const int *)(hcamcorder->cam_attrs_const_info[idx].validity_value_1.int_array),
-                                       hcamcorder->cam_attrs_const_info[idx].validity_value_2.count,
-                                       hcamcorder->cam_attrs_const_info[idx].default_value.value_int);
+                                       (const int *)(attr_info->validity_value_1.int_array),
+                                       attr_info->validity_value_2.count,
+                                       attr_info->default_value.value_int);
                        }
                        break;
                case MM_ATTRS_VALID_TYPE_INT_RANGE:
                        mmf_attrs_set_valid_range(attrs, idx,
-                               hcamcorder->cam_attrs_const_info[idx].validity_value_1.int_min,
-                               hcamcorder->cam_attrs_const_info[idx].validity_value_2.int_max,
-                               hcamcorder->cam_attrs_const_info[idx].default_value.value_int);
+                               attr_info->validity_value_1.int_min,
+                               attr_info->validity_value_2.int_max,
+                               attr_info->default_value.value_int);
                        break;
                case MM_ATTRS_VALID_TYPE_DOUBLE_ARRAY:
-                       if (hcamcorder->cam_attrs_const_info[idx].validity_value_1.double_array &&
-                           hcamcorder->cam_attrs_const_info[idx].validity_value_2.count > 0) {
+                       if (attr_info->validity_value_1.double_array &&
+                           attr_info->validity_value_2.count > 0) {
                                mmf_attrs_set_valid_double_array(attrs, idx,
-                                       (const double *)(hcamcorder->cam_attrs_const_info[idx].validity_value_1.double_array),
-                                       hcamcorder->cam_attrs_const_info[idx].validity_value_2.count,
-                                       hcamcorder->cam_attrs_const_info[idx].default_value.value_double);
+                                       (const double *)(attr_info->validity_value_1.double_array),
+                                       attr_info->validity_value_2.count,
+                                       attr_info->default_value.value_double);
                        }
                        break;
                case MM_ATTRS_VALID_TYPE_DOUBLE_RANGE:
                        mmf_attrs_set_valid_double_range(attrs, idx,
-                               hcamcorder->cam_attrs_const_info[idx].validity_value_1.double_min,
-                               hcamcorder->cam_attrs_const_info[idx].validity_value_2.double_max,
-                               hcamcorder->cam_attrs_const_info[idx].default_value.value_double);
+                               attr_info->validity_value_1.double_min,
+                               attr_info->validity_value_2.double_max,
+                               attr_info->default_value.value_double);
+                       ((mmf_attrs_t *)attrs)->items[idx].value.value.d_val = attr_info->default_value.value_double;
                        break;
                case MM_ATTRS_VALID_TYPE_NONE:
                        break;
@@ -4649,6 +4677,58 @@ bool _mmcamcorder_commit_tag(MMHandleType handle, int attr_idx, const mmf_value_
        return TRUE;
 }
 
+bool _mmcamcorder_commit_audio_replay_gain(MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+       mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+       mmf_return_val_if_fail(hcamcorder && value, FALSE);
+
+       if (attr_idx == MM_CAM_AUDIO_REPLAY_GAIN_ENABLE) {
+               /* Replay gain enable */
+               int current_state = MM_CAMCORDER_STATE_NONE;
+               int audio_disable = FALSE;
+
+               current_state = _mmcamcorder_get_state(handle);
+               if (current_state >= MM_CAMCORDER_STATE_RECORDING) {
+                       _mmcam_dbg_err("Can not set replay gain enable [state : %d]", current_state);
+                       hcamcorder->error_code = MM_ERROR_CAMCORDER_INVALID_STATE;
+                       return FALSE;
+               }
+
+               mm_camcorder_get_attributes(handle, NULL,
+                       MMCAM_AUDIO_DISABLE, &audio_disable,
+                       NULL);
+
+               if (audio_disable) {
+                       _mmcam_dbg_err("audio is disabled");
+                       hcamcorder->error_code = MM_ERROR_CAMCORDER_INVALID_CONDITION;
+                       return FALSE;
+               }
+
+               _mmcam_dbg_log("set replay gain enable : %d", value->value.i_val);
+       } else if (attr_idx == MM_CAM_AUDIO_REPLAY_GAIN_REFERENCE_LEVEL) {
+               /* Replay gain reference level */
+               int replay_gain_enable = FALSE;
+
+               mm_camcorder_get_attributes(handle, NULL,
+                       MMCAM_AUDIO_REPLAY_GAIN_ENABLE, &replay_gain_enable,
+                       NULL);
+
+               if (replay_gain_enable == FALSE) {
+                       _mmcam_dbg_err("replay gain is disabled");
+                       hcamcorder->error_code = MM_ERROR_CAMCORDER_INVALID_CONDITION;
+                       return FALSE;
+               }
+
+               _mmcam_dbg_log("set reference level for replay gain : %ld dB", value->value.d_val);
+       } else {
+               _mmcam_dbg_err("unknown attribute id %d", attr_idx);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 
 static bool __mmcamcorder_attrs_is_supported(MMHandleType handle, int idx)
 {
index 6206c0e..71930c6 100644 (file)
@@ -195,6 +195,11 @@ static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle)
        srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
        MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC,
                __mmcamcorder_audio_dataprobe_record, hcamcorder);
+
+       /* for replay gain tag */
+       MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC,
+               __mmcamcorder_eventprobe_monitor, hcamcorder);
+
        gst_object_unref(srcpad);
        srcpad = NULL;
 
index 27ce41f..58593e9 100644 (file)
@@ -486,6 +486,8 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle)
        int stream_index = 0;
        int buffer_interval = 0;
        int blocksize = 0;
+       int replay_gain_enable = FALSE;
+       double replay_gain_ref_level = 0.0;
 
        GstCaps *caps = NULL;
        GstPad *pad = NULL;
@@ -516,6 +518,8 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle)
                MMCAM_AUDIO_FORMAT, &format,
                MMCAM_AUDIO_CHANNEL, &channel,
                MMCAM_AUDIO_VOLUME, &volume,
+               MMCAM_AUDIO_REPLAY_GAIN_ENABLE, &replay_gain_enable,
+               MMCAM_AUDIO_REPLAY_GAIN_REFERENCE_LEVEL, &replay_gain_ref_level,
                MMCAM_SOUND_STREAM_TYPE, &stream_type, &stream_type_len,
                MMCAM_SOUND_STREAM_INDEX, &stream_index,
                NULL);
@@ -586,14 +590,13 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle)
        MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_QUE].gst, "max-size-bytes", 0);
        MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_QUE].gst, "max-size-time", 0);
 
-       if (a_enc != MM_AUDIO_CODEC_VORBIS)
-               _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_AUDIOSRC_VOL, "volume", "audiosrc_volume", element_list, err);
-
        /* Set basic infomation */
        if (a_enc != MM_AUDIO_CODEC_VORBIS) {
                int depth = 0;
                const gchar* format_name = NULL;
 
+               _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_AUDIOSRC_VOL, "volume", "audiosrc_volume", element_list, err);
+
                if (volume == 0.0) {
                        /* Because data probe of audio src do the same job, it doesn't need to set "mute" here. Already null raw data. */
                        MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_VOL].gst, "volume", 1.0);
@@ -628,6 +631,17 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle)
                        rate, channel, BYTE_ORDER);
        }
 
+       /* Replay Gain */
+       _mmcam_dbg_log("Replay gain - enable : %d, reference level : %lf",
+               replay_gain_enable, replay_gain_ref_level);
+
+       if (replay_gain_enable) {
+               _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_AUDIOSRC_RGA, "rganalysis", "audiosrc_rga", element_list, err);
+               MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_RGA].gst, "reference-level", replay_gain_ref_level);
+               /* If num-tracks is not set, album gain and peak event is not come. */
+               MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_RGA].gst, "num-tracks", 1);
+       }
+
        if (caps) {
                MMCAMCORDER_G_OBJECT_SET_POINTER((sc->encode_element[_MMCAMCORDER_AUDIOSRC_FILT].gst), "caps", caps);
                gst_caps_unref(caps);
@@ -2005,10 +2019,55 @@ GstPadProbeReturn __mmcamcorder_eventprobe_monitor(GstPad *pad, GstPadProbeInfo
        case GST_EVENT_NAVIGATION:
        case GST_EVENT_LATENCY:
        /* downstream serialized events */
-       case GST_EVENT_TAG:
        case GST_EVENT_BUFFERSIZE:
                _mmcam_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
                break;
+       case GST_EVENT_TAG:
+               {
+                       GstTagList *tag_list = NULL;
+                       _MMCamcorderReplayGain *replay_gain = NULL;
+
+                       _mmcam_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
+
+                       hcamcorder = MMF_CAMCORDER(u_data);
+                       if (!hcamcorder || !hcamcorder->sub_context) {
+                               _mmcam_dbg_warn("NULL handle");
+                               break;
+                       }
+
+                       replay_gain = &hcamcorder->sub_context->replay_gain;
+
+                       gst_event_parse_tag(event, &tag_list);
+                       if (!tag_list) {
+                               _mmcam_dbg_warn("failed to get tag list");
+                               break;
+                       }
+
+                       if (!gst_tag_list_get_double(tag_list, GST_TAG_TRACK_PEAK, &replay_gain->track_peak)) {
+                               _mmcam_dbg_warn("failed to get GST_TAG_TRACK_PEAK");
+                               break;
+                       }
+
+                       if (!gst_tag_list_get_double(tag_list, GST_TAG_TRACK_GAIN, &replay_gain->track_gain)) {
+                               _mmcam_dbg_warn("failed to get GST_TAG_TRACK_GAIN");
+                               break;
+                       }
+
+                       if (!gst_tag_list_get_double(tag_list, GST_TAG_ALBUM_PEAK, &replay_gain->album_peak)) {
+                               _mmcam_dbg_warn("failed to get GST_TAG_ALBUM_PEAK");
+                               break;
+                       }
+
+                       if (!gst_tag_list_get_double(tag_list, GST_TAG_ALBUM_GAIN, &replay_gain->album_gain)) {
+                               _mmcam_dbg_warn("failed to get GST_TAG_ALBUM_PEAK");
+                               break;
+                       }
+
+                       _mmcam_dbg_log("Track [peak %lf, gain %lf], Album [peak %lf, gain %lf]",
+                               replay_gain->track_peak, replay_gain->track_gain,
+                               replay_gain->album_peak, replay_gain->album_gain);
+               }
+               break;
        case GST_EVENT_SEGMENT:
                _mmcam_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));