[libmm-camcorder] tv product specific control
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_gstcommon.c
index f7fa967..a5efb16 100644 (file)
@@ -44,7 +44,7 @@ gboolean      audiocodec_fileformat_compatibility_table[MM_AUDIO_CODEC_NUM][MM_FILE_F
 {          /* 3GP ASF AVI MATROSKA MP4 OGG NUT QT REAL AMR AAC MP3 AIFF AU WAV MID MMF DIVX FLV VOB IMELODY WMA WMV JPG FLAC M2TS*/
 /*AMR*/       { 1,  0,  0,       0,  0,  0,  0, 0,   0,  1,  0,  0,   0, 0,  0,  0,  0,   0,  0,  0,      0,  0,  0,  0,   0,   0},
 /*G723.1*/    { 0,  0,  0,       0,  0,  0,  0, 0,   0,  0,  0,  0,   0, 0,  0,  0,  0,   0,  0,  0,      0,  0,  0,  0,   0,   0},
-/*MP3*/       { 0,  0,  0,       0,  0,  0,  0, 0,   0,  0,  0,  0,   0, 0,  0,  0,  0,   0,  0,  0,      0,  0,  0,  0,   0,   0},
+/*MP3*/       { 0,  1,  1,       1,  1,  0,  0, 1,   0,  0,  0,  1,   0, 0,  0,  0,  0,   0,  1,  0,      0,  0,  0,  0,   0,   1},
 /*OGG*/       { 0,  0,  0,       0,  0,  0,  0, 0,   0,  0,  0,  0,   0, 0,  0,  0,  0,   0,  0,  0,      0,  0,  0,  0,   0,   0},
 /*AAC*/       { 1,  0,  1,       1,  1,  0,  0, 0,   0,  0,  1,  0,   0, 0,  0,  0,  0,   0,  0,  0,      0,  0,  0,  0,   0,   1},
 /*WMA*/       { 0,  0,  0,       0,  0,  0,  0, 0,   0,  0,  0,  0,   0, 0,  0,  0,  0,   0,  0,  0,      0,  0,  0,  0,   0,   0},
@@ -132,7 +132,6 @@ gboolean    videocodec_fileformat_compatibility_table[MM_VIDEO_CODEC_NUM][MM_FILE_F
 #define _MMCAMCORDER_FRAME_PASS_MIN_FPS           30
 #define _MMCAMCORDER_NANOSEC_PER_1SEC             1000000000
 #define _MMCAMCORDER_NANOSEC_PER_1MILISEC         1000
-#define _MMCAMCORDER_VIDEO_DECODER_NAME           "avdec_h264"
 
 
 /*-----------------------------------------------------------------------
@@ -180,9 +179,14 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
        int display_surface_type = MM_DISPLAY_SURFACE_NULL;
        const char *videosrc_name = NULL;
        const char *videosink_name = NULL;
+       const char *videoconvert_name = NULL;
        char *err_name = NULL;
        char *socket_path = NULL;
        int socket_path_len;
+#ifdef _MMCAMCORDER_RM_SUPPORT
+       int decoder_index = 0;
+       char decoder_name[20] = {'\0',};
+#endif /* _MMCAMCORDER_RM_SUPPORT */
 
        GList *element_list = NULL;
 
@@ -293,6 +297,42 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
        if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
                int preview_bitrate = 0;
                int gop_interval = 0;
+               const char *videodecoder_name = NULL;
+
+               /* get recreate_decoder flag */
+               _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
+                       CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
+                       "RecreateDecoder",
+                       &hcamcorder->recreate_decoder);
+
+               /* get video decoder element and name for H.264 format */
+               _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
+                       CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
+                       "VideodecoderElementH264",
+                       &sc->VideodecoderElementH264);
+
+               _mmcamcorder_conf_get_value_element_name(sc->VideodecoderElementH264, &videodecoder_name);
+
+               if (videodecoder_name) {
+                       _mmcam_dbg_log("video decoder element [%s], recreate decoder %d",
+                               videodecoder_name, hcamcorder->recreate_decoder);
+#ifdef _MMCAMCORDER_RM_SUPPORT
+                       if (hcamcorder->request_resources.category_id[0] == RM_CATEGORY_VIDEO_DECODER_SUB)
+                               decoder_index = 1;
+
+                       snprintf(decoder_name, sizeof(decoder_name)-1, "%s%d", videodecoder_name, decoder_index);
+                       _mmcam_dbg_log("encoded preview decoder_name %s", decoder_name);
+                       /* create decoder element */
+                       _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_DECODE, decoder_name, "videosrc_decode", element_list, err);
+#else /* _MMCAMCORDER_RM_SUPPORT */
+                       /* create decoder element */
+                       _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_DECODE, videodecoder_name, "videosrc_decode", element_list, err);
+#endif /* _MMCAMCORDER_RM_SUPPORT */
+                       _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, sc->VideodecoderElementH264);
+               } else {
+                       _mmcam_dbg_err("failed to get video decoder element name from %p", sc->VideodecoderElementH264);
+                       goto pipeline_creation_error;
+               }
 
                /* set encoded preview bitrate and iframe interval */
                mm_camcorder_get_attributes(handle, NULL,
@@ -305,9 +345,6 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
 
                if (!_mmcamcorder_set_encoded_preview_gop_interval(handle, gop_interval))
                        _mmcam_dbg_warn("_mmcamcorder_set_encoded_preview_gop_interval failed");
-
-               /* create decoder element */
-               _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_DECODE, _MMCAMCORDER_VIDEO_DECODER_NAME, "videosrc_decode", element_list, err);
        }
 
        _mmcam_dbg_log("Current mode[%d]", hcamcorder->type);
@@ -322,9 +359,11 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
        if (display_surface_type == MM_DISPLAY_SURFACE_REMOTE) {
                _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSINK_SINK, videosink_name, "ipc_sink", element_list, err);
 
+               _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, sc->VideosinkElement);
+
                err = mm_camcorder_get_attributes(handle, &err_name,
-                                                 MMCAM_DISPLAY_SOCKET_PATH, &socket_path, &socket_path_len,
-                                                 NULL);
+                       MMCAM_DISPLAY_SOCKET_PATH, &socket_path, &socket_path_len,
+                       NULL);
                if (err != MM_ERROR_NONE) {
                        _mmcam_dbg_warn("Get socket path failed 0x%x", err);
                        SAFE_FREE(err_name);
@@ -333,7 +372,22 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
 
                g_object_set(G_OBJECT(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst), "socket-path", socket_path, NULL);
        } else {
+
+               if (hcamcorder->use_videoconvert && !strcmp(videosink_name, "waylandsink")) {
+                       /* get video convert name */
+                       _mmcamcorder_conf_get_value_element_name(sc->VideoconvertElement, &videoconvert_name);
+
+                       if (videoconvert_name) {
+                               _mmcam_dbg_log("videoconvert element name : %s", videoconvert_name);
+                               _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSINK_CLS, videoconvert_name, "videosink_cls", element_list, err);
+                       } else
+                               _mmcam_dbg_err("failed to get videoconvert element name");
+               }
+
                _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSINK_SINK, videosink_name, "videosink_sink", element_list, err);
+
+               _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, sc->VideosinkElement);
+
                if (_mmcamcorder_videosink_window_set(handle, sc->VideosinkElement) != MM_ERROR_NONE) {
                        _mmcam_dbg_err("_mmcamcorder_videosink_window_set error");
                        err = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
@@ -341,8 +395,6 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
                }
        }
 
-       _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, sc->VideosinkElement);
-
        /* Set caps by rotation */
        _mmcamcorder_set_videosrc_rotation(handle, camera_rotate);
 
@@ -1199,6 +1251,9 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi
        int zoom_attr = 0;
        int zoom_level = 0;
        int do_scaling = FALSE;
+#ifdef _MMCAMCORDER_RM_SUPPORT
+       int display_scaler = 0;
+#endif /* _MMCAMCORDER_RM_SUPPORT */
        int *overlay = NULL;
        gulong xid;
        char *err_name = NULL;
@@ -1261,6 +1316,12 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi
                        _mmcam_dbg_warn("Handle is NULL. Set xid as 0.. but, it's not recommended.");
                        gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), 0);
                }
+#ifdef _MMCAMCORDER_RM_SUPPORT
+               if (hcamcorder->request_resources.category_id[0] == RM_CATEGORY_VIDEO_DECODER_SUB)
+                       display_scaler = 1;
+
+               MMCAMCORDER_G_OBJECT_SET(vsink, "device-scaler", display_scaler);
+#endif /* _MMCAMCORDER_RM_SUPPORT */
        } else if (!strcmp(videosink_name, "evasimagesink") ||
                   !strcmp(videosink_name, "evaspixmapsink")) {
                _mmcam_dbg_log("videosink : %s, handle : %p", videosink_name, overlay);
@@ -1279,6 +1340,12 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi
                        gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(vsink), (guintptr)wl_info->global_surface_id);
                        gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(vsink),
                                wl_info->window_x, wl_info->window_y, wl_info->window_width, wl_info->window_height);
+#ifdef _MMCAMCORDER_RM_SUPPORT
+               if (hcamcorder->request_resources.category_id[0] == RM_CATEGORY_VIDEO_DECODER_SUB)
+                       display_scaler = 1;
+
+               MMCAMCORDER_G_OBJECT_SET(vsink, "device-scaler", display_scaler);
+#endif /* _MMCAMCORDER_RM_SUPPORT */
                } else {
                        _mmcam_dbg_warn("Handle is NULL. skip setting.");
                }
@@ -1594,6 +1661,10 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP
                                        stream.data.yuv420sp.length_y = stream.width * stream.height;
                                        stream.data.yuv420sp.uv = stream.data.yuv420sp.y + stream.data.yuv420sp.length_y;
                                        stream.data.yuv420sp.length_uv = stream.data.yuv420sp.length_y >> 1;
+                                       stream.stride[0] = stream.width;
+                                       stream.elevation[0] = stream.height;
+                                       stream.stride[1] = stream.width;
+                                       stream.elevation[1] = stream.height >> 1;
                                        /*
                                        _mmcam_dbg_log("format[%d][num_planes:%d] [Y]p:0x%x,size:%d [UV]p:0x%x,size:%d",
                                                       stream.format, stream.num_planes,
@@ -1609,6 +1680,12 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP
                                        stream.data.yuv420p.length_u = stream.data.yuv420p.length_y >> 2;
                                        stream.data.yuv420p.v = stream.data.yuv420p.u + stream.data.yuv420p.length_u;
                                        stream.data.yuv420p.length_v = stream.data.yuv420p.length_u;
+                                       stream.stride[0] = stream.width;
+                                       stream.elevation[0] = stream.height;
+                                       stream.stride[1] = stream.width >> 1;
+                                       stream.elevation[1] = stream.height >> 1;
+                                       stream.stride[2] = stream.width >> 1;
+                                       stream.elevation[2] = stream.height >> 1;
                                        /*
                                        _mmcam_dbg_log("I420[num_planes:%d] [Y]p:0x%x,size:%d [U]p:0x%x,size:%d [V]p:0x%x,size:%d",
                                                        stream.num_planes,
@@ -1631,6 +1708,8 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP
                                stream.data_type = MM_CAM_STREAM_DATA_YUV422;
                                stream.data.yuv422.yuv = mapinfo.data;
                                stream.data.yuv422.length_yuv = stream.length_total;
+                               stream.stride[0] = stream.width << 1;
+                               stream.elevation[0] = stream.height;
                        } else if (stream.format == MM_PIXEL_FORMAT_ENCODED_H264) {
                                        stream.data_type = MM_CAM_STREAM_DATA_ENCODED;
                                        stream.data.encoded.data = mapinfo.data;
@@ -1642,6 +1721,8 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP
                                stream.data_type = MM_CAM_STREAM_DATA_YUV420;
                                stream.data.yuv420.yuv = mapinfo.data;
                                stream.data.yuv420.length_yuv = stream.length_total;
+                               stream.stride[0] = (stream.width * 3) >> 1;
+                               stream.elevation[0] = stream.height;
                        }
 
                        stream.num_planes = 1;
@@ -2139,6 +2220,13 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in
        gboolean do_set_caps = FALSE;
 
        GstCaps *caps = NULL;
+#ifdef _MMCAMCORDER_PRODUCT_TV
+       GstPad *sinkpad;
+       GstCaps *decsink_caps = NULL;
+       GstStructure *decsink_struct = NULL;
+       int maxwidth = 0;
+       int maxheight = 0;
+#endif /*_MMCAMCORDER_PRODUCT_TV */
 
        mmf_camcorder_t *hcamcorder = NULL;
        _MMCamcorderSubContext *sc = NULL;
@@ -2250,6 +2338,32 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in
                        gst_structure_get_int(structure, "fps", &caps_fps);
                        gst_structure_get_int(structure, "rotate", &caps_rotate);
 
+#ifdef _MMCAMCORDER_PRODUCT_TV
+                       if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
+                               if (set_width == caps_width && set_height == caps_height && set_rotate == caps_rotate && fps == caps_fps) {
+                                       _mmcam_dbg_log("No need to replace caps.");
+                               } else {
+                                       _mmcam_dbg_log("current [%c%c%c%c %dx%d, fps %d, rot %d], new [%c%c%c%c %dx%d, fps %d, rot %d]",
+                                                      caps_fourcc, caps_fourcc>>8, caps_fourcc>>16, caps_fourcc>>24,
+                                                      caps_width, caps_height, caps_fps, caps_rotate,
+                                                      fourcc, fourcc>>8, fourcc>>16, fourcc>>24,
+                                                      set_width, set_height, fps, set_rotate);
+                                       do_set_caps = TRUE;
+                               }
+                       } else {
+                               if (set_width == caps_width && set_height == caps_height &&
+                                   fourcc == caps_fourcc && set_rotate == caps_rotate && fps == caps_fps) {
+                                       _mmcam_dbg_log("No need to replace caps.");
+                               } else {
+                                       _mmcam_dbg_log("current [%c%c%c%c %dx%d, fps %d, rot %d], new [%c%c%c%c %dx%d, fps %d, rot %d]",
+                                                      caps_fourcc, caps_fourcc>>8, caps_fourcc>>16, caps_fourcc>>24,
+                                                      caps_width, caps_height, caps_fps, caps_rotate,
+                                                      fourcc, fourcc>>8, fourcc>>16, fourcc>>24,
+                                                      set_width, set_height, fps, set_rotate);
+                                       do_set_caps = TRUE;
+                               }
+                       }
+#else /*_MMCAMCORDER_PRODUCT_TV */
                        if (set_width == caps_width && set_height == caps_height &&
                            fourcc == caps_fourcc && set_rotate == caps_rotate && fps == caps_fps) {
                                _mmcam_dbg_log("No need to replace caps.");
@@ -2261,6 +2375,7 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in
                                               set_width, set_height, fps, set_rotate);
                                do_set_caps = TRUE;
                        }
+#endif /*_MMCAMCORDER_PRODUCT_TV */
                } else {
                        _mmcam_dbg_log("can not get structure of caps. set new one...");
                        do_set_caps = TRUE;
@@ -2277,12 +2392,51 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in
 
        if (do_set_caps) {
                if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
+#ifdef _MMCAMCORDER_PRODUCT_TV
+                       sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, "sink");
+                       if (!sinkpad) {
+                               _mmcam_dbg_err("There are no decoder caps");
+                               return FALSE;
+                       }
+
+                       decsink_caps = gst_pad_get_pad_template_caps(sinkpad);
+                       if (!decsink_caps) {
+                               gst_object_unref(sinkpad);
+                               _mmcam_dbg_err("There is no decoder sink caps");
+                               return FALSE;
+                       }
+
+                       decsink_struct = gst_caps_get_structure(decsink_caps,0);
+                       if (!decsink_struct) {
+                               _mmcam_dbg_err("There are no structure from caps");
+                               gst_object_unref(decsink_caps);
+                               gst_object_unref(sinkpad);
+                               return FALSE;
+                       }
+
+                       if(gst_structure_has_field(decsink_struct, "maxwidth")){
+                               gst_structure_get_int(decsink_struct, "maxwidth", &maxwidth);
+                       }
+                       if(gst_structure_has_field(decsink_struct, "maxheight")){
+                               gst_structure_get_int(decsink_struct, "maxheight", &maxheight);
+                       }
+#endif /* _MMCAMCORDER_PRODUCT_TV */
                        caps = gst_caps_new_simple("video/x-h264",
                                        "width", G_TYPE_INT, set_width,
                                        "height", G_TYPE_INT, set_height,
                                        "framerate", GST_TYPE_FRACTION, fps, 1,
                                        "stream-format", G_TYPE_STRING, "byte-stream",
+#ifdef _MMCAMCORDER_PRODUCT_TV
+                                       "maxwidth", G_TYPE_INT, maxwidth,
+                                       "maxheight", G_TYPE_INT, maxheight,
+                                       "alignment", G_TYPE_STRING, "au",
+#endif /* _MMCAMCORDER_PRODUCT_TV */
                                        NULL);
+
+#ifdef _MMCAMCORDER_PRODUCT_TV
+                       gst_object_unref(decsink_caps);
+                       gst_object_unref(sinkpad);
+#endif /* _MMCAMCORDER_PRODUCT_TV */
                } else {
                        char fourcc_string[sizeof(fourcc)+1];
                        strncpy(fourcc_string, (char*)&fourcc, sizeof(fourcc));
@@ -2592,3 +2746,132 @@ bool _mmcamcorder_set_sound_stream_info(GstElement *element, char *stream_type,
        return TRUE;
 }
 
+
+bool _mmcamcorder_recreate_decoder_for_encoded_preview(MMHandleType handle)
+{
+       int ret = MM_ERROR_NONE;
+       _MMCamcorderSubContext *sc = NULL;
+       mmf_camcorder_t *hcamcorder = NULL;
+       const char *videodecoder_name = NULL;
+#ifdef _MMCAMCORDER_RM_SUPPORT
+       char decoder_name[20] = {'\0',};
+       int decoder_index = 0;
+#endif /* _MMCAMCORDER_RM_SUPPORT */
+
+       if ((void *)handle == NULL) {
+               _mmcam_dbg_warn("handle is NULL");
+               return FALSE;
+       }
+
+       hcamcorder = MMF_CAMCORDER(handle);
+
+       sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+       if (!sc) {
+               _mmcam_dbg_warn("subcontext is NULL");
+               return FALSE;
+       }
+
+       if (sc->info_image->preview_format != MM_PIXEL_FORMAT_ENCODED_H264 ||
+               hcamcorder->recreate_decoder == FALSE) {
+               _mmcam_dbg_log("skip this fuction - format %d, recreate decoder %d",
+                       sc->info_image->preview_format, hcamcorder->recreate_decoder);
+               return TRUE;
+       }
+
+       if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst == NULL ||
+           sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst == NULL) {
+               _mmcam_dbg_warn("main pipeline or decoder plugin is NULL");
+               return FALSE;
+       }
+
+       _mmcam_dbg_log("start");
+
+       _mmcamcorder_conf_get_value_element_name(sc->VideodecoderElementH264, &videodecoder_name);
+       if (videodecoder_name == NULL) {
+               _mmcam_dbg_err("failed to get decoder element name from %p", sc->VideodecoderElementH264);
+               return FALSE;
+       }
+
+       /* set state as NULL */
+       ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, GST_STATE_NULL);
+       if (ret != MM_ERROR_NONE) {
+               _mmcam_dbg_err("failed to set NULL to decoder");
+               return FALSE;
+       }
+
+       /* remove decoder - pads will be unlinked automatically in remove function */
+       if (!gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+                           sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)) {
+               _mmcam_dbg_err("failed to remove decoder from pipeline");
+               return FALSE;
+       }
+
+       /* check decoder element */
+       if (sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst) {
+               _mmcam_dbg_log("decoder[%p] is still alive - ref count %d",
+                       G_OBJECT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst),
+                       ((GObject *)sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)->ref_count);
+       }
+
+#ifdef _MMCAMCORDER_RM_SUPPORT
+       if (hcamcorder->request_resources.category_id[0] == RM_CATEGORY_VIDEO_DECODER_SUB)
+               decoder_index = 1;
+
+       snprintf(decoder_name, sizeof(decoder_name)-1, "%s%d", videodecoder_name, decoder_index);
+       _mmcam_dbg_log("encoded preview decoder_name %s", decoder_name);
+       /* create decoder */
+       sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst = gst_element_factory_make(decoder_name, "videosrc_decode");
+       if (sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst == NULL) {
+               _mmcam_dbg_err("Decoder[%s] creation fail", decoder_name);
+               return FALSE;
+       }
+#else /* _MMCAMCORDER_RM_SUPPORT */
+       /* create new decoder */
+       sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst = gst_element_factory_make(videodecoder_name, "videosrc_decode");
+       if (sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst == NULL) {
+               _mmcam_dbg_err("Decoder [%s] creation fail", videodecoder_name);
+               return FALSE;
+       }
+#endif /* _MMCAMCORDER_RM_SUPPORT */
+       _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, sc->VideodecoderElementH264);
+
+       sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].id = _MMCAMCORDER_VIDEOSRC_DECODE;
+       g_object_weak_ref(G_OBJECT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst),
+               (GWeakNotify)_mmcamcorder_element_release_noti, sc);
+
+       /* add to pipeline */
+       if (!gst_bin_add(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+               sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)) {
+               _mmcam_dbg_err("failed to add decoder to pipeline");
+               gst_object_unref(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst);
+               return FALSE;
+       }
+
+       /* link */
+       if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst),
+               GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst))) {
+               _mmcam_dbg_log("Link videosrc_queue to decoder OK");
+       } else {
+               _mmcam_dbg_err("Link videosrc_queue to decoder FAILED");
+               return FALSE;
+       }
+
+       if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst),
+               GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst))) {
+               _mmcam_dbg_log("Link decoder to videosink_queue OK");
+       } else {
+               _mmcam_dbg_err("Link decoder to videosink_queue FAILED");
+               return FALSE;
+       }
+
+       /* set state READY */
+       ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, GST_STATE_READY);
+       if (ret != MM_ERROR_NONE) {
+               _mmcam_dbg_err("failed to set READY to decoder");
+               return FALSE;
+       }
+
+       _mmcam_dbg_log("done");
+
+       return TRUE;
+}