Set display handle for directvideosink
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_gstcommon.c
index cd1db49..a0da705 100644 (file)
@@ -155,6 +155,10 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_push_buffer_to_record(Gst
 static int __mmcamcorder_get_amrnb_bitrate_mode(int bitrate);
 static guint32 _mmcamcorder_convert_fourcc_string_to_value(const gchar* format_name);
 
+#ifdef _MMCAMCORDER_PRODUCT_TV
+static bool __mmcamcorder_find_max_resolution(MMHandleType handle, gint *max_width, gint *max_height);
+#endif /* _MMCAMCORDER_PRODUCT_TV */
+
 /*=======================================================================================
 |  FUNCTION DEFINITIONS                                                                        |
 =======================================================================================*/
@@ -188,7 +192,10 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
        char decoder_name[20] = {'\0',};
 #endif /* _MMCAMCORDER_RM_SUPPORT */
        GstElement *sink_element = NULL;
+       GstCameraControl *control = NULL;
        int sink_element_size = 0;
+       int *fds = NULL;
+       int fd_number = 0;
 
        GList *element_list = NULL;
 
@@ -248,6 +255,21 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
                return err;
        }
 
+       if (hcamcorder->support_user_buffer) {
+               err = mm_camcorder_get_attributes(handle, NULL,
+                       MMCAM_USER_BUFFER_FD, &fds, &fd_number,
+                       NULL);
+               if (err != MM_ERROR_NONE || fd_number < 1) {
+                       _mmcam_dbg_err("get user buffer fd failed 0x%x, number %d", err, fd_number);
+                       return err;
+               }
+
+               /*
+               for (i = 0 ; i < fd_number ; i++)
+                       _mmcam_dbg_log("fds[%d] %d", i, fds[i]);
+               */
+       }
+
        /* Get fourcc from picture format */
        sc->fourcc = _mmcamcorder_get_fourcc(sc->info_image->preview_format, codectype, hcamcorder->use_zero_copy_format);
 
@@ -294,8 +316,17 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle)
        /* Set video device index */
        MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "camera-id", input_index->default_value);
 
+       /* set user buffer fd to videosrc element */
+       if (hcamcorder->support_user_buffer) {
+               control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+               if (!gst_camera_control_set_user_buffer_fd(control, fds, fd_number)) {
+                       _mmcam_dbg_err("set user buffer fd failed");
+                       goto pipeline_creation_error;
+               }
+       }
+
        /* make demux and decoder for H264 stream from videosrc */
-       if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
+       if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 && display_surface_type != MM_DISPLAY_SURFACE_NULL) {
                int preview_bitrate = 0;
                int gop_interval = 0;
                const char *videodecoder_name = NULL;
@@ -1350,7 +1381,8 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi
 #ifdef _MMCAMCORDER_RM_SUPPORT
        int display_scaler = 0;
 #endif /* _MMCAMCORDER_RM_SUPPORT */
-       int *overlay = NULL;
+       int *dp_handle = NULL;
+       MMCamWindowInfo *window_info = NULL;
        gulong xid;
        char *err_name = NULL;
        const char *videosink_name = NULL;
@@ -1380,7 +1412,7 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi
                MMCAM_DISPLAY_ROTATION, &rotation,
                MMCAM_DISPLAY_FLIP, &flip,
                MMCAM_DISPLAY_VISIBLE, &visible,
-               MMCAM_DISPLAY_HANDLE, (void**)&overlay, &size,
+               MMCAM_DISPLAY_HANDLE, (void **)&dp_handle, &size,
                MMCAM_DISPLAY_MODE, &display_mode,
                MMCAM_DISPLAY_GEOMETRY_METHOD, &display_geometry_method,
                MMCAM_DISPLAY_SCALE, &zoom_attr,
@@ -1404,13 +1436,12 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi
                return MM_ERROR_CAMCORDER_INTERNAL;
        }
 
-       _mmcam_dbg_log("(overlay=%p, size=%d)", overlay, size);
+       _mmcam_dbg_log("(dp_handle=%p, size=%d)", dp_handle, size);
 
        /* Set display handle */
-       if (!strcmp(videosink_name, "xvimagesink") ||
-           !strcmp(videosink_name, "ximagesink")) {
-               if (overlay) {
-                       xid = *overlay;
+       if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "ximagesink")) {
+               if (dp_handle) {
+                       xid = *dp_handle;
                        _mmcam_dbg_log("xid = %lu )", xid);
                        gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), xid);
                } else {
@@ -1424,22 +1455,46 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi
                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);
+               _mmcam_dbg_log("videosink : %s, handle : %p", videosink_name, dp_handle);
 
-               if (overlay) {
-                       MMCAMCORDER_G_OBJECT_SET_POINTER(vsink, "evas-object", overlay);
+               if (dp_handle) {
+                       MMCAMCORDER_G_OBJECT_SET_POINTER(vsink, "evas-object", dp_handle);
                        MMCAMCORDER_G_OBJECT_SET(vsink, "origin-size", !do_scaling);
                } else {
                        _mmcam_dbg_err("display handle(eavs object) is NULL");
                        return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
                }
-       } else if (!strcmp(videosink_name, "tizenwlsink") || !strcmp(videosink_name, "directvideosink")) {
-               if (overlay) {
-                       _mmcam_dbg_log("wayland global surface id : %d", *(int *)(overlay));
-                       gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(vsink), (guintptr)*(int *)(overlay));
+       } else if (!strcmp(videosink_name, "tizenwlsink")) {
+               if (dp_handle) {
+                       window_info = (MMCamWindowInfo *)dp_handle;
+                       _mmcam_dbg_log("wayland global surface id : %d", window_info->surface_id);
+                       gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(vsink), window_info->surface_id);
                } else {
                        _mmcam_dbg_warn("Handle is NULL. skip setting.");
                }
+       } else if (!strcmp(videosink_name, "directvideosink")) {
+               if (dp_handle) {
+                       window_info = (MMCamWindowInfo *)dp_handle;
+                       _mmcam_dbg_log("wayland global surface id : %d, x,y,w,h (%d,%d,%d,%d)",
+                               window_info->surface_id,
+                               window_info->rect.x,
+                               window_info->rect.y,
+                               window_info->rect.width,
+                               window_info->rect.height);
+                       gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), (guintptr)window_info->surface_id);
+                       gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(vsink),
+                               window_info->rect.x,
+                               window_info->rect.y,
+                               window_info->rect.width,
+                               window_info->rect.height);
+               } else {
+                       _mmcam_dbg_warn("dp_handle is null");
+               }
+#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("Who are you?? (Videosink: %s)", videosink_name);
        }
@@ -1669,10 +1724,12 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP
                GstMemory *memory = NULL;
                GstMapInfo mapinfo;
 
-               state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
-               if (state < MM_CAMCORDER_STATE_PREPARE) {
-                       _mmcam_dbg_warn("Not ready for stream callback");
-                       return GST_PAD_PROBE_OK;
+               if (sc->info_image->preview_format != MM_PIXEL_FORMAT_ENCODED_H264) {
+                       state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
+                       if (state < MM_CAMCORDER_STATE_PREPARE) {
+                               _mmcam_dbg_warn("Not ready for stream callback");
+                               return GST_PAD_PROBE_OK;
+                       }
                }
 
                caps = gst_pad_get_current_caps(pad);
@@ -1718,7 +1775,10 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP
                }
 
                /* set size and timestamp */
-               memory = gst_buffer_peek_memory(buffer, 0);
+               if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264)
+                       memory = gst_buffer_get_all_memory(buffer);
+               else
+                       memory = gst_buffer_peek_memory(buffer, 0);
                if (!memory) {
                        _mmcam_dbg_err("GstMemory get failed from buffer %p", buffer);
                        return GST_PAD_PROBE_OK;
@@ -1904,6 +1964,8 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP
                /* unmap memory */
                if (mapinfo.data)
                        gst_memory_unmap(memory, &mapinfo);
+               if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264)
+                       gst_memory_unref(memory);
        }
 
        return GST_PAD_PROBE_OK;
@@ -2164,7 +2226,7 @@ GstPadProbeReturn __mmcamcorder_eventprobe_monitor(GstPad *pad, GstPadProbeInfo
                        const GstSegment *segment;
                        gst_event_parse_segment(event, &segment);
                        if (segment->format == GST_FORMAT_BYTES) {
-                               _mmcam_dbg_log("change current offset %llu -> %llu",
+                               _mmcam_dbg_log("change current offset %llu -> %"G_GUINT64_FORMAT,
                                        sc->muxed_stream_offset, segment->start);
 
                                sc->muxed_stream_offset = (unsigned long long)segment->start;
@@ -2493,13 +2555,6 @@ 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;
@@ -2662,34 +2717,21 @@ 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;
-                       }
+                       gint maxwidth = 0;
+                       gint maxheight = 0;
+                       int display_surface_type = MM_DISPLAY_SURFACE_NULL;
+                       mm_camcorder_get_attributes(handle, NULL,
+                                       MMCAM_DISPLAY_SURFACE, &display_surface_type,
+                                       NULL);
 
-                       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 (display_surface_type != MM_DISPLAY_SURFACE_NULL && __mmcamcorder_find_max_resolution(handle, &maxwidth, &maxheight) == false) {
+                               _mmcam_dbg_err("can not find max resolution limitation");
+                               return false;
+                       } else if (display_surface_type == MM_DISPLAY_SURFACE_NULL) {
+                               maxwidth = set_width;
+                               maxheight = set_height;
                        }
-
-                       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,
@@ -2701,11 +2743,6 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in
                                "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));
@@ -3146,3 +3183,65 @@ bool _mmcamcorder_recreate_decoder_for_encoded_preview(MMHandleType handle)
 
        return TRUE;
 }
+
+#ifdef _MMCAMCORDER_PRODUCT_TV
+static bool __mmcamcorder_find_max_resolution(MMHandleType handle, gint *max_width, gint *max_height)
+{
+       _MMCamcorderSubContext *sc = NULL;
+       mmf_camcorder_t *hcamcorder = NULL;
+       int index = 0;
+       const gchar *mime = NULL;
+       GstPad *sinkpad;
+       GstCaps *decsink_caps = NULL;
+       GstStructure *decsink_struct = NULL;
+
+       mmf_return_val_if_fail(handle, false);
+       mmf_return_val_if_fail(max_width, false);
+       mmf_return_val_if_fail(max_height, false);
+
+       hcamcorder = MMF_CAMCORDER(handle);
+       mmf_return_val_if_fail(hcamcorder, false);
+
+       sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+
+       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;
+       }
+
+       for (index = 0; index < gst_caps_get_size(decsink_caps); index++) {
+               decsink_struct = gst_caps_get_structure(decsink_caps, index);
+               if (!decsink_struct) {
+                       _mmcam_dbg_err("There are no structure from caps");
+                       gst_object_unref(decsink_caps);
+                       gst_object_unref(sinkpad);
+                       return false;
+               }
+               mime = gst_structure_get_name(decsink_struct);
+               if (!strcmp(mime, "video/x-h264")) {
+                       _mmcam_dbg_log("h264 caps structure found");
+                       if (gst_structure_has_field(decsink_struct, "maxwidth"))
+                               *max_width = gst_value_get_int_range_max(gst_structure_get_value(decsink_struct, "maxwidth"));
+                       if (gst_structure_has_field(decsink_struct, "maxheight"))
+                               *max_height = gst_value_get_int_range_max(gst_structure_get_value(decsink_struct, "maxheight"));
+                       break;
+               }
+       }
+       _mmcam_dbg_log("maxwidth = %d , maxheight = %d", (int)*max_width, (int)*max_height);
+       gst_object_unref(decsink_caps);
+       gst_object_unref(sinkpad);
+
+       if (*max_width <= 0 || *max_height <= 0)
+               return false;
+
+       return true;
+}
+#endif /* _MMCAMCORDER_PRODUCT_TV */