X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmm_camcorder_gstcommon.c;h=a5efb16684bc9c7e9debc45d57e9b5cf8ae76006;hb=41c25b884f3ed112d8ea9145463065e2816cd070;hp=5d4e2530a1d90bbad508ecbc726038fd55449d39;hpb=1f695c046648c0285a0e5cacd1f5655405f5a08c;p=platform%2Fcore%2Fmultimedia%2Flibmm-camcorder.git diff --git a/src/mm_camcorder_gstcommon.c b/src/mm_camcorder_gstcommon.c index 5d4e253..a5efb16 100644 --- a/src/mm_camcorder_gstcommon.c +++ b/src/mm_camcorder_gstcommon.c @@ -35,7 +35,6 @@ #include "mm_camcorder_internal.h" #include "mm_camcorder_gstcommon.h" -#include "mm_camcorder_client.h" /*----------------------------------------------------------------------- | GLOBAL VARIABLE DEFINITIONS for internal | @@ -45,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}, @@ -133,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" /*----------------------------------------------------------------------- @@ -181,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; @@ -234,7 +237,7 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle) MMCAM_CAMERA_HDR_CAPTURE, &sc->info_image->hdr_capture_mode, MMCAM_IMAGE_ENCODER, &codectype, MMCAM_IMAGE_ENCODER_QUALITY, &capture_jpg_quality, - MMCAM_DISPLAY_SHM_SOCKET_PATH, &socket_path, &socket_path_len, + MMCAM_DISPLAY_SOCKET_PATH, &socket_path, &socket_path_len, MMCAM_DISPLAY_SURFACE, &display_surface_type, NULL); if (err != MM_ERROR_NONE) { @@ -292,7 +295,56 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle) /* make demux and decoder for H264 stream from videosrc */ if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { - _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_DECODE, _MMCAMCORDER_VIDEO_DECODER_NAME, "videosrc_decode", element_list, err); + 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, + MMCAM_ENCODED_PREVIEW_BITRATE, &preview_bitrate, + MMCAM_ENCODED_PREVIEW_GOP_INTERVAL, &gop_interval, + NULL); + + if (!_mmcamcorder_set_encoded_preview_bitrate(handle, preview_bitrate)) + _mmcam_dbg_warn("_mmcamcorder_set_encoded_preview_bitrate failed"); + + if (!_mmcamcorder_set_encoded_preview_gop_interval(handle, gop_interval)) + _mmcam_dbg_warn("_mmcamcorder_set_encoded_preview_gop_interval failed"); } _mmcam_dbg_log("Current mode[%d]", hcamcorder->type); @@ -307,21 +359,41 @@ 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_SHM_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); - return err; + goto pipeline_creation_error; } 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); + _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; + goto pipeline_creation_error; + } + } /* Set caps by rotation */ _mmcamcorder_set_videosrc_rotation(handle, camera_rotate); @@ -380,6 +452,9 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) char *err_name = NULL; const char *audiosrc_name = NULL; char *cat_name = NULL; + char *stream_type = NULL; + char stream_type_len = 0; + int stream_index = 0; GstCaps *caps = NULL; GstPad *pad = NULL; @@ -404,14 +479,16 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) } err = mm_camcorder_get_attributes(handle, &err_name, - MMCAM_AUDIO_DEVICE, &a_dev, - MMCAM_AUDIO_ENCODER, &a_enc, - MMCAM_AUDIO_ENCODER_BITRATE, &val, - MMCAM_AUDIO_SAMPLERATE, &rate, - MMCAM_AUDIO_FORMAT, &format, - MMCAM_AUDIO_CHANNEL, &channel, - MMCAM_AUDIO_VOLUME, &volume, - NULL); + MMCAM_AUDIO_DEVICE, &a_dev, + MMCAM_AUDIO_ENCODER, &a_enc, + MMCAM_AUDIO_ENCODER_BITRATE, &val, + MMCAM_AUDIO_SAMPLERATE, &rate, + MMCAM_AUDIO_FORMAT, &format, + MMCAM_AUDIO_CHANNEL, &channel, + MMCAM_AUDIO_VOLUME, &volume, + MMCAM_SOUND_STREAM_TYPE, &stream_type, &stream_type_len, + MMCAM_SOUND_STREAM_INDEX, &stream_index, + NULL); if (err != MM_ERROR_NONE) { _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err); SAFE_FREE(err_name); @@ -455,6 +532,10 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_AUDIOSRC_SRC, audiosrc_name, "audiosrc_src", element_list, err); + /* set sound stream info */ + _mmcamcorder_set_sound_stream_info(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, stream_type, stream_index); + + /* set audiosrc properties in ini configuration */ _mmcamcorder_conf_set_value_element_property(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, AudiosrcElement); _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_AUDIOSRC_FILT, "capsfilter", "audiosrc_capsfilter", element_list, err); @@ -641,26 +722,31 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "max-bytes", 0); /* unlimited */ /* set capsfilter */ - if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { - _mmcam_dbg_log("get pad from videosrc_filter"); - pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "src"); + if (profile == MM_CAMCORDER_ENCBIN_PROFILE_VIDEO) { + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + _mmcam_dbg_log("get pad from videosrc_filter"); + pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "src"); + } else { + _mmcam_dbg_log("get pad from videosrc_que"); + pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "src"); + } + if (!pad) { + _mmcam_dbg_err("get videosrc_que src pad failed"); + err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; + goto pipeline_creation_error; + } + + caps_from_pad = gst_pad_get_allowed_caps(pad); + video_caps = gst_caps_copy(caps_from_pad); + gst_caps_unref(caps_from_pad); + caps_from_pad = NULL; + gst_object_unref(pad); + pad = NULL; } else { - _mmcam_dbg_log("get pad from videosrc_que"); - pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "src"); - } - if (!pad) { - _mmcam_dbg_err("get videosrc_que src pad failed"); - err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; - goto pipeline_creation_error; + /* Image */ + MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", &video_caps); } - caps_from_pad = gst_pad_get_allowed_caps(pad); - video_caps = gst_caps_copy(caps_from_pad); - gst_caps_unref(caps_from_pad); - caps_from_pad = NULL; - gst_object_unref(pad); - pad = NULL; - if (video_caps) { char *caps_str = NULL; @@ -673,7 +759,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin caps_str = gst_caps_to_string(video_caps); _mmcam_dbg_log("encodebin caps [%s]", caps_str); - free(caps_str); + g_free(caps_str); caps_str = NULL; MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "caps", video_caps); @@ -696,13 +782,24 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_ENCBIN, "encodebin", "encodesink_encbin", element_list, err); /* check element availability */ - mm_camcorder_get_attributes(handle, &err_name, + err = mm_camcorder_get_attributes(handle, &err_name, MMCAM_AUDIO_ENCODER, &audio_enc, MMCAM_AUDIO_CHANNEL, &channel, MMCAM_VIDEO_ENCODER_BITRATE, &v_bitrate, MMCAM_AUDIO_ENCODER_BITRATE, &a_bitrate, NULL); + if (err != MM_ERROR_NONE) { + if (err_name) { + _mmcam_dbg_err("failed to get attributes [%s][0x%x]", err_name, err); + SAFE_FREE(err_name); + } else { + _mmcam_dbg_err("failed to get attributes [0x%x]", err); + } + + return err; + } + _mmcam_dbg_log("Profile[%d]", profile); /* Set information */ @@ -753,7 +850,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin } if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { - gst_element_venc_name = strdup("capsfilter"); + gst_element_venc_name = "capsfilter"; } else { _mmcamcorder_conf_get_value_element_name(VideoencElement, &gst_element_venc_name); } @@ -808,11 +905,6 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin if (use_venc_queue) { _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_VENC_QUE, "use-venc-queue", err); } - - if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { - free(gst_element_venc_name); - gst_element_venc_name = NULL; - } } if (sc->audio_disable == FALSE && @@ -1019,11 +1111,6 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin element_list = NULL; } - if (video_caps) { - gst_caps_unref(video_caps); - video_caps = NULL; - } - _mmcam_dbg_log("done"); return MM_ERROR_NONE; @@ -1046,11 +1133,6 @@ pipeline_creation_error : element_list = NULL; } - if (video_caps) { - gst_caps_unref(video_caps); - video_caps = NULL; - } - return err; } @@ -1169,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; @@ -1208,8 +1293,7 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi if (err != MM_ERROR_NONE) { if (err_name) { _mmcam_dbg_err("failed to get attributes [%s][0x%x]", err_name, err); - free(err_name); - err_name = NULL; + SAFE_FREE(err_name); } else { _mmcam_dbg_err("failed to get attributes [0x%x]", err); } @@ -1232,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); @@ -1246,21 +1336,16 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi } else if (!strcmp(videosink_name, "waylandsink")) { MMCamWaylandInfo *wl_info = (MMCamWaylandInfo *)overlay; if (wl_info) { - GstContext *context = NULL; - - context = gst_wayland_display_handle_context_new((struct wl_display *)wl_info->display); - if (context) { - gst_element_set_context(vsink, context); - } else { - _mmcam_dbg_warn("gst_wayland_display_handle_context_new failed"); - } - - gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), (guintptr)wl_info->surface); + _mmcam_dbg_log("wayland global surface id : %d", wl_info->global_surface_id); + 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); + 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."); } @@ -1273,7 +1358,7 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi videosink_name, display_geometry_method, origin_size, visible, rotation, flip); /* Set attribute */ - if (!strcmp(videosink_name, "xvimagesink") || + if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "waylandsink") || !strcmp(videosink_name, "evaspixmapsink")) { /* set rotation */ MMCAMCORDER_G_OBJECT_SET(vsink, "rotate", rotation); @@ -1342,7 +1427,7 @@ gboolean _mmcamcorder_get_device_info(MMHandleType handle) mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; GstCameraControl *control = NULL; - GstCameraControlExifInfo exif_info; + GstCameraControlExifInfo exif_info = {0,}; mmf_return_val_if_fail(hcamcorder, FALSE); sc = MMF_CAMCORDER_SUBCONTEXT(handle); @@ -1360,7 +1445,8 @@ gboolean _mmcamcorder_get_device_info(MMHandleType handle) control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); if (control != NULL) { gst_camera_control_get_exif_info(control, &exif_info); //get video input device information - focal_len = ((double)exif_info.focal_len_numerator) / ((double) exif_info.focal_len_denominator); + if (exif_info.focal_len_denominator != 0) + focal_len = ((double)exif_info.focal_len_numerator) / ((double) exif_info.focal_len_denominator); } else { _mmcam_dbg_err("Fail to get camera control interface!"); focal_len = 0.0; @@ -1373,10 +1459,7 @@ gboolean _mmcamcorder_get_device_info(MMHandleType handle) NULL); if (err != MM_ERROR_NONE) { _mmcam_dbg_err("Set attributes error(%s:%x)!", err_name, err); - if (err_name) { - free(err_name); - err_name = NULL; - } + SAFE_FREE(err_name); return FALSE; } } else { @@ -1495,16 +1578,19 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP structure = gst_caps_get_structure( caps, 0 ); gst_structure_get_int(structure, "width", &(stream.width)); gst_structure_get_int(structure, "height", &(stream.height)); - string_format = gst_structure_get_string(structure, "format"); - if (string_format == NULL) { - gst_caps_unref(caps); - caps = NULL; - _mmcam_dbg_warn("get string error!!"); - return GST_PAD_PROBE_OK; + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + stream.format = MM_PIXEL_FORMAT_ENCODED_H264; + } else { + string_format = gst_structure_get_string(structure, "format"); + if (string_format == NULL) { + gst_caps_unref(caps); + caps = NULL; + _mmcam_dbg_warn("get string error!!"); + return GST_PAD_PROBE_OK; + } + fourcc = _mmcamcorder_convert_fourcc_string_to_value(string_format); + stream.format = _mmcamcorder_get_pixtype(fourcc); } - - fourcc = _mmcamcorder_convert_fourcc_string_to_value(string_format); - stream.format = _mmcamcorder_get_pixtype(fourcc); gst_caps_unref(caps); caps = NULL; @@ -1575,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, @@ -1590,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, @@ -1612,10 +1708,21 @@ 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; + stream.data.encoded.length_data = stream.length_total; + _mmcam_dbg_log("H264[num_planes:%d] [0]p:0x%x,size:%d", + fourcc, fourcc>>8, fourcc>>16, fourcc>>24, stream.num_planes, + stream.data.encoded.data, stream.data.encoded.length_data); } else { 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; @@ -1718,11 +1825,11 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_push_buffer_to_record(Gst if(sc->info_video->is_firstframe) { /* for image capture with encodebin(ex:emulator) */ if (sc->bencbin_capture && sc->info_image->capturing) { - pthread_mutex_lock(&(hcamcorder->task_thread_lock)); + g_mutex_lock(&hcamcorder->task_thread_lock); _mmcam_dbg_log("send signal for sound play"); hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_SOUND_SOLO_PLAY_START; - pthread_cond_signal(&(hcamcorder->task_thread_cond)); - pthread_mutex_unlock(&(hcamcorder->task_thread_lock)); + g_cond_signal(&hcamcorder->task_thread_cond); + g_mutex_unlock(&hcamcorder->task_thread_lock); } sc->info_video->is_firstframe = FALSE; sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer); @@ -1739,7 +1846,7 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_push_buffer_to_record(Gst char *caps_string = gst_caps_to_string(caps); if (caps_string) { _mmcam_dbg_log("%s", caps_string); - free(caps_string); + g_free(caps_string); caps_string = NULL; } gst_caps_unref(caps); @@ -1938,8 +2045,8 @@ int _mmcamcorder_check_audiocodec_fileformat_compatibility(MMHandleType handle) } /* Check compatibility between audio codec and file format */ - if (audio_codec >= MM_AUDIO_CODEC_INVALID && audio_codec < MM_AUDIO_CODEC_NUM && - file_format >= MM_FILE_FORMAT_INVALID && file_format < MM_FILE_FORMAT_NUM) { + if (audio_codec > MM_AUDIO_CODEC_INVALID && audio_codec < MM_AUDIO_CODEC_NUM && + file_format > MM_FILE_FORMAT_INVALID && file_format < MM_FILE_FORMAT_NUM) { if (audiocodec_fileformat_compatibility_table[audio_codec][file_format] == 0) { _mmcam_dbg_err("Audio codec[%d] and file format[%d] compatibility FAILED.", audio_codec, file_format); @@ -1977,8 +2084,8 @@ int _mmcamcorder_check_videocodec_fileformat_compatibility(MMHandleType handle) } /* Check compatibility between audio codec and file format */ - if (video_codec >= MM_VIDEO_CODEC_INVALID && video_codec < MM_VIDEO_CODEC_NUM && - file_format >= MM_FILE_FORMAT_INVALID && file_format < MM_FILE_FORMAT_NUM) { + if (video_codec > MM_VIDEO_CODEC_INVALID && video_codec < MM_VIDEO_CODEC_NUM && + file_format > MM_FILE_FORMAT_INVALID && file_format < MM_FILE_FORMAT_NUM) { if (videocodec_fileformat_compatibility_table[video_codec][file_format] == 0) { _mmcam_dbg_err("Video codec[%d] and file format[%d] compatibility FAILED.", video_codec, file_format); @@ -1997,7 +2104,7 @@ int _mmcamcorder_check_videocodec_fileformat_compatibility(MMHandleType handle) } -bool _mmcamcorder_set_display_rotation(MMHandleType handle, int display_rotate) +bool _mmcamcorder_set_display_rotation(MMHandleType handle, int display_rotate, int videosink_index) { const char* videosink_name = NULL; @@ -2011,7 +2118,7 @@ bool _mmcamcorder_set_display_rotation(MMHandleType handle, int display_rotate) mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED); mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED); - if (sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst) { + if (sc->element[videosink_index].gst) { /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); if (videosink_name == NULL) { @@ -2019,10 +2126,9 @@ bool _mmcamcorder_set_display_rotation(MMHandleType handle, int display_rotate) return FALSE; } - if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "evasimagesink") || - !strcmp(videosink_name, "evaspixmapsink")) { - MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, - "rotate", display_rotate); + if (!strcmp(videosink_name, "waylandsink") || !strcmp(videosink_name, "xvimagesink") || + !strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { + MMCAMCORDER_G_OBJECT_SET(sc->element[videosink_index].gst, "rotate", display_rotate); _mmcam_dbg_log("Set display-rotate [%d] done.", display_rotate); return TRUE; } else { @@ -2036,7 +2142,7 @@ bool _mmcamcorder_set_display_rotation(MMHandleType handle, int display_rotate) } -bool _mmcamcorder_set_display_flip(MMHandleType handle, int display_flip) +bool _mmcamcorder_set_display_flip(MMHandleType handle, int display_flip, int videosink_index) { const char* videosink_name = NULL; @@ -2050,7 +2156,7 @@ bool _mmcamcorder_set_display_flip(MMHandleType handle, int display_flip) mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED); mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED); - if (sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst) { + if (sc->element[videosink_index].gst) { /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); if (videosink_name == NULL) { @@ -2058,10 +2164,9 @@ bool _mmcamcorder_set_display_flip(MMHandleType handle, int display_flip) return FALSE; } - if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "evasimagesink") || - !strcmp(videosink_name, "evaspixmapsink")) { - MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, - "flip", display_flip); + if (!strcmp(videosink_name, "waylandsink") || !strcmp(videosink_name, "xvimagesink") || + !strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { + MMCAMCORDER_G_OBJECT_SET(sc->element[videosink_index].gst, "flip", display_flip); _mmcam_dbg_log("Set display flip [%d] done.", display_flip); return TRUE; } else { @@ -2115,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; @@ -2211,17 +2323,47 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in structure = gst_caps_get_structure(caps, 0); if (structure) { + const gchar *format_string = NULL; int caps_width = 0; int caps_height = 0; int caps_fps = 0; int caps_rotate = 0; - caps_fourcc = _mmcamcorder_convert_fourcc_string_to_value(gst_structure_get_string(structure, "format")); + format_string = gst_structure_get_string(structure, "format"); + if (format_string) { + caps_fourcc = _mmcamcorder_convert_fourcc_string_to_value(format_string); + } gst_structure_get_int(structure, "width", &caps_width); gst_structure_get_int(structure, "height", &caps_height); 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."); @@ -2233,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; @@ -2249,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)); @@ -2268,11 +2450,14 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in NULL); } - _mmcam_dbg_log("vidoesrc new caps set. %"GST_PTR_FORMAT, caps); - - MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps); - gst_caps_unref(caps); - caps = NULL; + if (caps) { + _mmcam_dbg_log("vidoesrc new caps set. %"GST_PTR_FORMAT, caps); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps); + gst_caps_unref(caps); + caps = NULL; + } else { + _mmcam_dbg_err("There are no caps"); + } } if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) { @@ -2452,3 +2637,241 @@ bool _mmcamcorder_set_camera_resolution(MMHandleType handle, int width, int heig return _mmcamcorder_set_videosrc_caps(handle, sc->fourcc, width, height, fps, sc->videosrc_rotate); } + + +bool _mmcamcorder_set_encoded_preview_bitrate(MMHandleType handle, int bitrate) +{ + _MMCamcorderSubContext *sc = NULL; + GstCameraControl *CameraControl = NULL; + GstCameraControlChannel *CameraControlChannel = NULL; + const GList *controls = NULL; + const GList *item = NULL; + + if ((void *)handle == NULL) { + _mmcam_dbg_warn("handle is NULL"); + return FALSE; + } + + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + if (!sc) { + _mmcam_dbg_warn("subcontext is NULL"); + return FALSE; + } + + if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst == NULL) { + _mmcam_dbg_warn("videosrc plugin is NULL"); + return FALSE; + } + + _mmcam_dbg_log("set encoded preview bitrate : %d bps", bitrate); + + CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + controls = gst_camera_control_list_channels(CameraControl); + _mmcam_dbg_log("controls : 0x%x", controls); + if (controls != NULL) { + _mmcam_dbg_log("controls : 0x%x", controls); + for (item = controls ; item && item->data ; item = item->next) { + CameraControlChannel = item->data; + _mmcam_dbg_log("label : %d", CameraControlChannel->label); + if (!strcmp(CameraControlChannel->label, "bitrate")) { + _mmcam_dbg_log("set encoded preview bitrate %d", bitrate); + return gst_camera_control_set_value(CameraControl, CameraControlChannel, bitrate); + } + } + + if (item == NULL) { + _mmcam_dbg_warn("failed to find \"bitrate\" control channel"); + } + } + + return FALSE; +} + + +bool _mmcamcorder_set_encoded_preview_gop_interval(MMHandleType handle, int interval) +{ + _MMCamcorderSubContext *sc = NULL; + + if ((void *)handle == NULL) { + _mmcam_dbg_warn("handle is NULL"); + return FALSE; + } + + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + if (!sc) { + _mmcam_dbg_warn("subcontext is NULL"); + return FALSE; + } + + if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst == NULL) { + _mmcam_dbg_warn("videosrc plugin is NULL"); + return FALSE; + } + + _mmcam_dbg_log("set encoded preview GOP interval : %d ms", interval); + + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "newgop-interval", interval); + + return TRUE; +} + + +bool _mmcamcorder_set_sound_stream_info(GstElement *element, char *stream_type, int stream_index) +{ + GstStructure *props = NULL; + char stream_props[64] = {'\0',}; + + if (element == NULL || stream_type == NULL || stream_index < 0) { + _mmcam_dbg_err("invalid argument %p %p %d", element, stream_type, stream_index); + return FALSE; + } + + snprintf(stream_props, sizeof(stream_props) - 1, + "props,media.role=%s, media.parent_id=%d", + stream_type, stream_index); + + _mmcam_dbg_log("stream type %s, index %d -> [%s]", stream_type, stream_index, stream_props); + + props = gst_structure_from_string(stream_props, NULL); + if (!props) { + _mmcam_dbg_err("failed to create GstStructure"); + return FALSE; + } + + MMCAMCORDER_G_OBJECT_SET_POINTER(element, "stream-properties", props); + + gst_structure_free(props); + props = NULL; + + 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; +}