[Release version 0.10.49] Update code for encoded preview format
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_gstcommon.c
index 5fabb05..8fa89c2 100644 (file)
@@ -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"
 
 
 /*-----------------------------------------------------------------------
@@ -294,6 +292,34 @@ 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);
+
+                       /* create decoder element */
+                       _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_DECODE, videodecoder_name, "videosrc_decode", element_list, err);
+
+                       _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,
@@ -306,9 +332,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);
@@ -401,6 +424,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;
@@ -425,14 +451,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);
@@ -476,6 +504,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);
@@ -662,26 +694,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;
 
@@ -785,7 +822,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);
                }
@@ -840,11 +877,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 &&
@@ -1267,21 +1299,10 @@ 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);
                } else {
                        _mmcam_dbg_warn("Handle is NULL. skip setting.");
                }
@@ -1294,7 +1315,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);
@@ -1597,6 +1618,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,
@@ -1612,6 +1637,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,
@@ -1634,6 +1665,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;
@@ -1645,6 +1678,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;
@@ -2563,3 +2598,145 @@ bool _mmcamcorder_set_encoded_preview_gop_interval(MMHandleType handle, int inte
 
        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;
+
+       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);
+       }
+
+       /* 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;
+       }
+
+       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;
+}