X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmm_camcorder_stillshot.c;h=0a6c85f10ab525f316d1c760b7e2581e98cd10a9;hb=0f2f6448e5628d10c43b18598fee7e9ef7628f91;hp=305172d2b4ead0564de834d1cbf71936b2d232be;hpb=da72a32bcfc44dd42a017af2b14dad35be519c13;p=platform%2Fcore%2Fmultimedia%2Flibmm-camcorder.git diff --git a/src/mm_camcorder_stillshot.c b/src/mm_camcorder_stillshot.c index 305172d..0a6c85f 100644 --- a/src/mm_camcorder_stillshot.c +++ b/src/mm_camcorder_stillshot.c @@ -33,6 +33,11 @@ #include #include +#ifdef _MMCAMCORDER_CAMERA_BOOST_SUPPORT +#include "mm_camcorder_boost.h" +#endif /* _MMCAMCORDER_CAMERA_BOOST_SUPPORT */ + + /*--------------------------------------------------------------------------------------- | GLOBAL VARIABLE DEFINITIONS for internal | ---------------------------------------------------------------------------------------*/ @@ -59,15 +64,34 @@ do { \ | LOCAL FUNCTION PROTOTYPES: | ---------------------------------------------------------------------------------------*/ /** STATIC INTERNAL FUNCTION **/ -/* Functions for JPEG capture without Encode bin */ -int _mmcamcorder_image_cmd_capture(MMHandleType handle); -int _mmcamcorder_image_cmd_preview_start(MMHandleType handle); -int _mmcamcorder_image_cmd_preview_stop(MMHandleType handle); +static int __mmcamcorder_image_cmd_capture(MMHandleType handle); +static int __mmcamcorder_image_cmd_preview_start(MMHandleType handle); +static int __mmcamcorder_image_cmd_preview_stop(MMHandleType handle); + +static int __mmcamcorder_capture_mode_init_camera_control(MMHandleType handle); +static int __mmcamcorder_capture_mode_init_encodebin(MMHandleType handle); +static int __mmcamcorder_capture_mode_init_image_pad(MMHandleType handle); +static int __mmcamcorder_capture_mode_deinit_encodebin(MMHandleType handle); + +static int __mmcamcorder_extra_preview_mode_init_camera_control(mmf_camcorder_t *hcamcorder); +static int __mmcamcorder_extra_preview_mode_deinit_camera_control(mmf_camcorder_t *hcamcorder); +static int __mmcamcorder_extra_preview_mode_init_pipeline(MMHandleType handle, MMCamcorderExtraPreviewMode mode); +static int __mmcamcorder_extra_preview_mode_deinit_pipeline(MMHandleType handle, MMCamcorderExtraPreviewMode mode); + +static int __mmcamcorder_set_exif_basic_info(MMHandleType handle, int image_width, int image_height); +static int __mmcamcorder_update_exif_info(MMHandleType handle, void *imagedata, int imgln); +static void __mmcamcorder_init_stillshot_info(MMHandleType handle); +static void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstSample *sample); +static void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, int tag_enable, int provide_exif); +static int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail, int provide_exif); +static int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail, int provide_exif); + +static gboolean __mmcamcorder_handoff_callback_capture(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data); +static gboolean __mmcamcorder_handoff_callback_extra_preview(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data); + static void __mmcamcorder_image_capture_cb(GstElement *element, GstSample *sample1, GstSample *sample2, GstSample *sample3, gpointer u_data); static void __mmcamcorder_extra_preview_stream_cb(GstElement *element, int stream_id, GstSample *sample, gpointer u_data); - -/* sound status changed callback */ -static void __sound_status_changed_cb(keynode_t* node, void *data); +static void __mmcamcorder_sound_status_changed_cb(keynode_t* node, void *data); /*======================================================================================= | FUNCTION DEFINITIONS | @@ -78,7 +102,7 @@ static void __sound_status_changed_cb(keynode_t* node, void *data); ---------------------------------------------------------------------------------------*/ -int _mmcamcorder_create_stillshot_pipeline(MMHandleType handle) +static int __mmcamcorder_capture_mode_init_encodebin(MMHandleType handle) { int err = MM_ERROR_UNKNOWN; GstPad *srcpad = NULL; @@ -107,34 +131,34 @@ int _mmcamcorder_create_stillshot_pipeline(MMHandleType handle) /* add element and encodesink bin to encode main pipeline */ gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, - sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, + sc->encode_element[_MMCAMCORDER_ENCSINK_CAPS].gst, sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, NULL); /* Link each element : appsrc - capsfilter - encodesink bin */ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "src"); - sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "sink"); + sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_CAPS].gst, "sink"); _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error); - srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "src"); + srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_CAPS].gst, "src"); sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "image_sink0"); _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error); /* connect handoff signal to get capture data */ MMCAMCORDER_SIGNAL_CONNECT(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, _MMCAMCORDER_HANDLER_STILLSHOT, "handoff", - G_CALLBACK(__mmcamcorder_handoff_callback), + G_CALLBACK(__mmcamcorder_handoff_callback_capture), hcamcorder); return MM_ERROR_NONE; pipeline_creation_error: - _mmcamcorder_remove_stillshot_pipeline(handle); + __mmcamcorder_capture_mode_deinit_encodebin(handle); return err; } -int _mmcamcorder_connect_capture_signal(MMHandleType handle) +static int __mmcamcorder_capture_mode_init_camera_control(MMHandleType handle) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; @@ -157,52 +181,378 @@ int _mmcamcorder_connect_capture_signal(MMHandleType handle) } -int _mmcamcorder_initialize_extra_preview_stream(MMHandleType handle) +static int __mmcamcorder_capture_mode_init_image_pad(MMHandleType handle) { - int i = 0; + int err = MM_ERROR_NONE; + int capture_width = 0; + int capture_height = 0; + int capture_quality = 0; + char *err_name = NULL; + gchar *caps_string = NULL; + GstCaps *caps = NULL; + GList *element_list = NULL; + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; - GstCameraControl *control = NULL; - _MMCamcorderExtraPreviewStreamFormat *e_fmt = NULL; mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); sc = MMF_CAMCORDER_SUBCONTEXT(handle); + mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + + err = mm_camcorder_get_attributes(handle, &err_name, + MMCAM_CAPTURE_WIDTH, &capture_width, + MMCAM_CAPTURE_HEIGHT, &capture_height, + MMCAM_IMAGE_ENCODER_QUALITY, &capture_quality, + NULL); + if (err != MM_ERROR_NONE) { + MMCAM_LOG_WARNING("Get attrs fail. (%s:%x)", err_name, err); + SAFE_FREE(err_name); + return err; + } + + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_CAP_CAPS, "capsfilter", "vsrc_c_c", element_list, err); + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_CAP_SINK, "fakesink", "vsrc_c_s", element_list, err); + + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_CAP_SINK].gst, "sync", TRUE); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_CAP_SINK].gst, "async", FALSE); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_CAP_SINK].gst, "enable-last-sample", FALSE); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_CAP_SINK].gst, "signal-handoffs", TRUE); + + caps = gst_caps_new_simple("image/jpeg", + "width", G_TYPE_INT, capture_width, + "height", G_TYPE_INT, capture_height, + NULL); + if (!caps) { + MMCAM_LOG_ERROR("caps for capture failed"); + err = MM_ERROR_CAMCORDER_GST_LINK; + goto pipeline_creation_error; + } + + caps_string = gst_caps_to_string(caps); + if (caps_string) { + MMCAM_LOG_INFO("set caps for capture[%s]", caps_string); + g_free(caps_string); + caps_string = NULL; + } + + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSRC_CAP_CAPS].gst, "caps", caps); + gst_caps_unref(caps); + + /* add elements to main pipeline */ + if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), element_list)) { + MMCAM_LOG_ERROR("element_list add error."); + err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; + goto pipeline_creation_error; + } + + /* link elements */ + if (!gst_element_link_pads(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "image_%u", + sc->element[_MMCAMCORDER_VIDEOSRC_CAP_CAPS].gst, "sink")) { + MMCAM_LOG_ERROR("capture pad link failed"); + err = MM_ERROR_CAMCORDER_GST_LINK; + goto pipeline_creation_error; + } + + if (!_mmcamcorder_link_elements(element_list)) { + MMCAM_LOG_ERROR("element link error."); + err = MM_ERROR_CAMCORDER_GST_LINK; + goto pipeline_creation_error; + } + + g_list_free(element_list); + + /* connect handoff signal to get capture data */ + MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_CAP_SINK].gst, + _MMCAMCORDER_HANDLER_STILLSHOT, "handoff", + G_CALLBACK(__mmcamcorder_handoff_callback_capture), + hcamcorder); + + return MM_ERROR_NONE; + +pipeline_creation_error: + _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CAP_CAPS); + _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CAP_SINK); + + if (element_list) { + g_list_free(element_list); + element_list = NULL; + } + + return err; +} + + +int _mmcamcorder_initialize_capture_mode(MMHandleType handle) +{ + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + + if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_CAMERA_CONTROL) + return __mmcamcorder_capture_mode_init_camera_control(handle); + else if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_IMAGE_PAD) + return __mmcamcorder_capture_mode_init_image_pad(handle); + + return MM_ERROR_NONE; +} + + +static int __mmcamcorder_extra_preview_mode_init_camera_control(mmf_camcorder_t *hcamcorder) +{ + int i = 0; + _MMCamcorderSubContext *sc = NULL; + GstCameraControl *control = NULL; + _MMCamcorderExtraPreviewFormat *e_fmt = NULL; + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + + sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED); mmf_return_val_if_fail(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, MM_ERROR_CAMCORDER_NOT_INITIALIZED); - MMCAM_LOG_INFO("connect extra preview stream signal to _MMCAMCORDER_VIDEOSRC_SRC"); + control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + if (!control) { + MMCAM_LOG_ERROR("no camera control"); + return MM_ERROR_CAMCORDER_NOT_SUPPORTED; + } + + MMCAM_LOG_INFO("connect extra preview stream signal and enable extra preview"); + + for (i = 0 ; i < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_MAX ; i++) { + e_fmt = &hcamcorder->extra_preview.format[i]; + + if (e_fmt->need_to_set_format) { + if (!gst_camera_control_set_extra_preview_stream_format(control, + i, _mmcamcorder_get_pixel_format2(e_fmt->pixel_format), + e_fmt->width, e_fmt->height, e_fmt->fps)) + MMCAM_LOG_WARNING("set format[%d,%dx%d,%d] failed for stream[%d]", + e_fmt->pixel_format, e_fmt->width, e_fmt->height, e_fmt->fps, i); + + e_fmt->need_to_set_format = FALSE; + } + + if (e_fmt->need_to_set_bitrate) { + if (!gst_camera_control_set_extra_preview_bitrate(control, i, e_fmt->bitrate)) + MMCAM_LOG_WARNING("set bitrate[%d] failed for stream[%d]", e_fmt->bitrate, i); + + e_fmt->need_to_set_bitrate = FALSE; + } + + if (e_fmt->need_to_set_gop_interval) { + if (!gst_camera_control_set_extra_preview_gop_interval(control, i, e_fmt->gop_interval)) + MMCAM_LOG_WARNING("set GOP interval[%d] failed for stream[%d]", e_fmt->gop_interval, i); + + e_fmt->need_to_set_gop_interval = FALSE; + } + } MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, _MMCAMCORDER_HANDLER_EXTRA_PREVIEW, "extra-preview-stream-cb", G_CALLBACK(__mmcamcorder_extra_preview_stream_cb), hcamcorder); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "extra-preview", TRUE); + + MMCAM_LOG_INFO("done"); + + return MM_ERROR_NONE; +} + + +static int __mmcamcorder_extra_preview_mode_deinit_camera_control(mmf_camcorder_t *hcamcorder) +{ + _MMCamcorderSubContext *sc = NULL; + GstCameraControl *control = NULL; + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + + sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); + mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + + mmf_return_val_if_fail(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); if (!control) { MMCAM_LOG_ERROR("no camera control"); return MM_ERROR_CAMCORDER_NOT_SUPPORTED; } - for (i = 0 ; i < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_NUM ; i++) { - e_fmt = &hcamcorder->extra_preview_format[i]; + MMCAM_LOG_INFO("disable extra preview and disconnect extra preview stream signal"); - if (!e_fmt->is_set) - continue; + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "extra-preview", FALSE); - if (!gst_camera_control_set_extra_preview_stream_format(control, - i, _mmcamcorder_get_pixel_format2(e_fmt->pixel_format), - e_fmt->width, e_fmt->height, e_fmt->fps)) - MMCAM_LOG_WARNING("set failed[%d],[%d,%dx%d,%d]", - i, e_fmt->pixel_format, e_fmt->width, e_fmt->height, e_fmt->fps); + _mmcamcorder_disconnect_signal((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_EXTRA_PREVIEW); + + MMCAM_LOG_INFO("done"); + + return MM_ERROR_NONE; +} + + +static int __mmcamcorder_extra_preview_mode_init_pipeline(MMHandleType handle, MMCamcorderExtraPreviewMode mode) +{ + int err = MM_ERROR_NONE; + int extra_preview_enable = 0; + int width = 0; + int height = 0; + int fps = 0; + const char *videosrc_name = NULL; + GstCaps *caps = NULL; + GList *element_list = NULL; + + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); + _MMCamcorderSubContext *sc = NULL; + type_element *videosrc_element = NULL; + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + + sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); + mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + + err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL, + MMCAM_EXTRA_PREVIEW_ENABLE, &extra_preview_enable, + NULL); + + width = hcamcorder->extra_preview.format[0].width; + height = hcamcorder->extra_preview.format[0].height; + fps = hcamcorder->extra_preview.format[0].fps; + + if (!extra_preview_enable || width <= 0 || height <= 0 || fps <= 0) { + MMCAM_LOG_WARNING("extra preview disabled[enable:%d,res:%dx%d,fps:%d]", + extra_preview_enable, width, height, fps); + return MM_ERROR_NONE; + } + + if (mode == MM_CAMCORDER_EXTRA_PREVIEW_MODE_PIPELINE_ELEMENT) { + _mmcamcorder_conf_get_element_and_name(handle, + hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT, "VideosrcElement", + &videosrc_element, &videosrc_name); + + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_EXT_SRC, videosrc_name, "vsrc_e_src", element_list, err); + + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_SRC].gst, "hal-name", NULL); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_SRC].gst, "camera-id", hcamcorder->extra_preview.camera_id[0]); + + _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_SRC].gst, videosrc_element); } + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_EXT_CAPS, "capsfilter", "vsrc_e_c", element_list, err); + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_EXT_SINK, "fakesink", "vsrc_e_sink", element_list, err); + + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_SINK].gst, "sync", TRUE); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_SINK].gst, "async", FALSE); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_SINK].gst, "enable-last-sample", FALSE); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_SINK].gst, "signal-handoffs", TRUE); + + caps = _mmcamcorder_get_video_caps((MMHandleType)hcamcorder, + hcamcorder->extra_preview.format[0].pixel_format, + width, height, fps, -1); + if (!caps) { + MMCAM_LOG_ERROR("caps for extra preview failed"); + err = MM_ERROR_CAMCORDER_GST_LINK; + goto pipeline_creation_error; + } + + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_CAPS].gst, "caps", caps); + gst_caps_unref(caps); + + /* add elements to main pipeline */ + if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), element_list)) { + MMCAM_LOG_ERROR("element_list add error."); + err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; + goto pipeline_creation_error; + } + + /* link elements */ + if (mode == MM_CAMCORDER_EXTRA_PREVIEW_MODE_PIPELINE_SRCPAD) { + if (!gst_element_link_pads(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video_%u", + sc->element[_MMCAMCORDER_VIDEOSRC_EXT_CAPS].gst, "sink")) { + MMCAM_LOG_ERROR("pad for extra preview link failed"); + err = MM_ERROR_CAMCORDER_GST_LINK; + goto pipeline_creation_error; + } + } + + if (!_mmcamcorder_link_elements(element_list)) { + MMCAM_LOG_ERROR("element link error."); + err = MM_ERROR_CAMCORDER_GST_LINK; + goto pipeline_creation_error; + } + + g_list_free(element_list); + + /* connect handoff signal to get capture data */ + MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_EXT_SINK].gst, + _MMCAMCORDER_HANDLER_STILLSHOT, "handoff", + G_CALLBACK(__mmcamcorder_handoff_callback_extra_preview), + hcamcorder); + + return MM_ERROR_NONE; + +pipeline_creation_error: + _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_EXT_CAPS); + _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_EXT_SINK); + + if (element_list) { + g_list_free(element_list); + element_list = NULL; + } + + return err; +} + + +static int __mmcamcorder_extra_preview_mode_deinit_pipeline(MMHandleType handle, MMCamcorderExtraPreviewMode mode) +{ + /* TODO */ return MM_ERROR_NONE; } -int _mmcamcorder_remove_stillshot_pipeline(MMHandleType handle) +int _mmcamcorder_initialize_extra_preview_mode(MMHandleType handle) +{ + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + + switch (hcamcorder->extra_preview.mode) { + case MM_CAMCORDER_EXTRA_PREVIEW_MODE_CAMERA_CONTROL: + return __mmcamcorder_extra_preview_mode_init_camera_control(handle); + case MM_CAMCORDER_EXTRA_PREVIEW_MODE_PIPELINE_SRCPAD: + case MM_CAMCORDER_EXTRA_PREVIEW_MODE_PIPELINE_ELEMENT: + return __mmcamcorder_extra_preview_mode_init_pipeline(handle, hcamcorder->extra_preview.mode); + default: + MMCAM_LOG_ERROR("unknown extra preview mode[%d]", hcamcorder->extra_preview.mode); + return MM_ERROR_CAMCORDER_INTERNAL; + } +} + + +int _mmcamcorder_deinitialize_extra_preview_mode(MMHandleType handle) +{ + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + + switch (hcamcorder->extra_preview.mode) { + case MM_CAMCORDER_EXTRA_PREVIEW_MODE_CAMERA_CONTROL: + return __mmcamcorder_extra_preview_mode_deinit_camera_control(handle); + case MM_CAMCORDER_EXTRA_PREVIEW_MODE_PIPELINE_SRCPAD: + case MM_CAMCORDER_EXTRA_PREVIEW_MODE_PIPELINE_ELEMENT: + return __mmcamcorder_extra_preview_mode_deinit_pipeline(handle, hcamcorder->extra_preview.mode); + default: + MMCAM_LOG_ERROR("unknown extra preview mode[%d]", hcamcorder->extra_preview.mode); + return MM_ERROR_CAMCORDER_INTERNAL; + } +} + + +static int __mmcamcorder_capture_mode_deinit_encodebin(MMHandleType handle) { int ret = MM_ERROR_NONE; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); @@ -333,10 +683,9 @@ _REUSE_CHECK_DONE: } -int _mmcamcorder_image_cmd_capture(MMHandleType handle) +static int __mmcamcorder_image_cmd_capture(MMHandleType handle) { int ret = MM_ERROR_NONE; - int UseCaptureMode = 0; int width = 0; int height = 0; int fps = 0; @@ -368,11 +717,6 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) return MM_ERROR_CAMCORDER_DEVICE_BUSY; } - _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main, - CONFIGURE_CATEGORY_MAIN_CAPTURE, - "UseCaptureMode", - &UseCaptureMode); - /* get current state */ mm_camcorder_get_state(handle, ¤t_state); @@ -421,7 +765,7 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) /* check state */ if (current_state >= MM_CAMCORDER_STATE_RECORDING) { - if (sc->bencbin_capture) { + if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_ENCODEBIN) { MMCAM_LOG_ERROR("could not capture in this target while recording"); ret = MM_ERROR_CAMCORDER_INVALID_STATE; goto cmd_done; @@ -455,7 +799,10 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) sc->internal_encode = FALSE; - if (!sc->bencbin_capture) { + if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_IMAGE_PAD) { + MMCAM_LOG_INFO("emit signal[capture-image]"); + g_signal_emit_by_name(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-image"); + } else if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_CAMERA_CONTROL) { /* Check encoding method */ if (info->capture_format == MM_PIXEL_FORMAT_ENCODED) { if ((sc->SensorEncodedCapture && info->type == _MMCamcorder_SINGLE_SHOT) || @@ -492,20 +839,9 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); gst_camera_control_set_capture_command(control, GST_CAMERA_CONTROL_CAPTURE_COMMAND_START); } else { - int need_change = 0; - int set_width = 0; - int set_height = 0; int cap_jpeg_quality = 0; - if (UseCaptureMode) { - if (width != MMFCAMCORDER_HIGHQUALITY_WIDTH || height != MMFCAMCORDER_HIGHQUALITY_HEIGHT) - need_change = 1; - } else { - if (width != info->width || height != info->height) - need_change = 1; - } - - if (need_change) { + if (width != info->width || height != info->height) { int rotation = 0; MMCAM_LOG_INFO("Need to change resolution"); @@ -530,14 +866,6 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) goto cmd_done; } - if (UseCaptureMode) { - set_width = MMFCAMCORDER_HIGHQUALITY_WIDTH; - set_height = MMFCAMCORDER_HIGHQUALITY_HEIGHT; - } else { - set_width = info->width; - set_height = info->height; - } - mm_camcorder_get_attributes(handle, &err_name, MMCAM_CAMERA_ROTATION, &rotation, NULL); @@ -547,7 +875,7 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) } /* set new caps */ - ret = _mmcamcorder_set_videosrc_caps(handle, sc->fourcc, set_width, set_height, fps, rotation); + ret = _mmcamcorder_set_videosrc_caps(handle, sc->fourcc, info->width, info->height, fps, rotation); if (!ret) { MMCAM_LOG_ERROR("_mmcamcorder_set_videosrc_caps failed"); ret = MM_ERROR_CAMCORDER_INTERNAL; @@ -566,14 +894,13 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) goto cmd_done; } - MMCAM_LOG_INFO("Change to target resolution(%d, %d)", set_width, set_height); + MMCAM_LOG_INFO("Change to target resolution(%d, %d)", info->width, info->height); } else { MMCAM_LOG_INFO("No need to change resolution. Open toggle now."); info->resolution_change = FALSE; } - /* add encodesinkbin */ - ret = _mmcamcorder_create_stillshot_pipeline((MMHandleType)hcamcorder); + ret = __mmcamcorder_capture_mode_init_encodebin((MMHandleType)hcamcorder); if (ret != MM_ERROR_NONE) { MMCAM_LOG_ERROR("failed to create encodesinkbin %x", ret); goto cmd_done; @@ -656,7 +983,7 @@ cmd_done: } -int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) +static int __mmcamcorder_image_cmd_preview_start(MMHandleType handle) { int ret = MM_ERROR_NONE; int width = 0; @@ -699,7 +1026,7 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) current_state = _mmcamcorder_get_state(handle); MMCAM_LOG_INFO("current state [%d]", current_state); - if (!sc->bencbin_capture) { + if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_CAMERA_CONTROL) { MMCAM_LOG_INFO("Preview start"); /* just set capture stop command if current state is CAPTURING */ @@ -762,7 +1089,7 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) gst_element_get_state(pipeline, &state, NULL, -1); if (state == GST_STATE_PLAYING) { - if (!sc->bencbin_capture) { + if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_CAMERA_CONTROL) { int try_count = 0; if (hcamcorder->support_zsl_capture == FALSE) { @@ -788,8 +1115,8 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) MMCAM_LOG_INFO("Wait Frame Done. count before[%d],after[%d], try_count[%d]", current_framecount, sc->kpi.video_framecount, try_count); - } else { - ret = _mmcamcorder_remove_stillshot_pipeline(handle); + } else if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_ENCODEBIN) { + ret = __mmcamcorder_capture_mode_deinit_encodebin(handle); if (ret != MM_ERROR_NONE) goto cmd_error; @@ -845,19 +1172,13 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) _mmcamcorder_sound_finalize(handle); } else { if (_mmcamcorder_is_encoded_preview_pixel_format(info->preview_format)) { - ret = mm_camcorder_get_attributes(handle, NULL, + mm_camcorder_get_attributes(handle, NULL, MMCAM_ENCODED_PREVIEW_BITRATE, &bitrate, + MMCAM_ENCODED_PREVIEW_GOP_INTERVAL, &gop_interval, NULL); - if (ret == MM_ERROR_NONE) - _mmcamcorder_set_encoded_preview_bitrate(handle, bitrate); - if (info->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { - ret = mm_camcorder_get_attributes(handle, NULL, - MMCAM_ENCODED_PREVIEW_GOP_INTERVAL, &gop_interval, - NULL); - if (ret == MM_ERROR_NONE) - _mmcamcorder_set_encoded_preview_gop_interval(handle, gop_interval); - } + _mmcamcorder_set_encoded_preview_bitrate(handle, bitrate); + _mmcamcorder_set_encoded_preview_gop_interval(handle, gop_interval); } MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); @@ -881,13 +1202,17 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) MMCAM_LOG_INFO("register vconf changed_cb and get sound status"); /* register changed_cb */ - vconf_notify_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, __sound_status_changed_cb, hcamcorder); + vconf_notify_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, __mmcamcorder_sound_status_changed_cb, hcamcorder); /* get sound status */ vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &(info->sound_status)); MMCAM_LOG_INFO("sound status %d", info->sound_status); } + +#ifdef _MMCAMCORDER_CAMERA_BOOST_SUPPORT + _mmcamcorder_start_boosting(); +#endif /* _MMCAMCORDER_CAMERA_BOOST_SUPPORT */ } cmd_error: @@ -895,7 +1220,7 @@ cmd_error: } -int _mmcamcorder_image_cmd_preview_stop(MMHandleType handle) +static int __mmcamcorder_image_cmd_preview_stop(MMHandleType handle) { int ret = MM_ERROR_NONE; int strobe_mode = MM_CAMCORDER_STROBE_MODE_OFF; @@ -973,7 +1298,7 @@ int _mmcamcorder_image_cmd_preview_stop(MMHandleType handle) if (sc->info_image->sound_status != _SOUND_STATUS_INIT) { MMCAM_LOG_INFO("deregister sound status callback"); - vconf_ignore_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, __sound_status_changed_cb); + vconf_ignore_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, __mmcamcorder_sound_status_changed_cb); sc->info_image->sound_status = _SOUND_STATUS_INIT; } @@ -998,16 +1323,21 @@ int _mmcamcorder_video_capture_command(MMHandleType handle, int command) switch (command) { case _MMCamcorder_CMD_CAPTURE: - ret = _mmcamcorder_image_cmd_capture(handle); + ret = __mmcamcorder_image_cmd_capture(handle); break; case _MMCamcorder_CMD_PREVIEW_START: - ret = _mmcamcorder_image_cmd_preview_start(handle); + ret = __mmcamcorder_image_cmd_preview_start(handle); /* I place this function last because it miscalculates a buffer that sents in GST_STATE_PAUSED */ _mmcamcorder_video_current_framerate_init(handle); break; case _MMCamcorder_CMD_PREVIEW_STOP: - ret = _mmcamcorder_image_cmd_preview_stop(handle); + ret = __mmcamcorder_image_cmd_preview_stop(handle); + +#ifdef _MMCAMCORDER_CAMERA_BOOST_SUPPORT + _mmcamcorder_stop_boosting(); +#endif /*_MMCAMCORDER_CAMERA_BOOST_SUPPORT */ + break; case _MMCamcorder_CMD_RECORD: case _MMCamcorder_CMD_PAUSE: @@ -1025,7 +1355,7 @@ int _mmcamcorder_video_capture_command(MMHandleType handle, int command) } -void __mmcamcorder_init_stillshot_info(MMHandleType handle) +static void __mmcamcorder_init_stillshot_info(MMHandleType handle) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; @@ -1054,7 +1384,7 @@ void __mmcamcorder_init_stillshot_info(MMHandleType handle) } -int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail, int provide_exif) +static int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail, int provide_exif) { int ret = MM_ERROR_NONE; unsigned char *data = NULL; @@ -1117,7 +1447,7 @@ int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureD } -void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstSample *sample) +static void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstSample *sample) { GstCaps *caps = NULL; GstMapInfo mapinfo; @@ -1142,8 +1472,10 @@ void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capt gst_buffer_map(gst_sample_get_buffer(sample), &mapinfo, GST_MAP_READ); capture_data->data = mapinfo.data; capture_data->format = pixtype; - gst_structure_get_int(structure, "width", &capture_data->width); - gst_structure_get_int(structure, "height", &capture_data->height); + gst_structure_get(structure, + "width", G_TYPE_INT, &capture_data->width, + "height", G_TYPE_INT, &capture_data->height, + NULL); capture_data->length = mapinfo.size; gst_buffer_unmap(gst_sample_get_buffer(sample), &mapinfo); @@ -1161,7 +1493,7 @@ GET_FAILED: } -int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail, int provide_exif) +static int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail, int provide_exif) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; @@ -1182,7 +1514,7 @@ int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType } -void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, int tag_enable, int provide_exif) +static void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, int tag_enable, int provide_exif) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; @@ -1330,7 +1662,7 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstSample *sampl memset((void *)&scrnail, 0x0, sizeof(MMCamcorderCaptureDataType)); /* Prepare main, thumbnail buffer */ - pixtype_main = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample1)); + pixtype_main = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample1), FALSE); if (pixtype_main == MM_PIXEL_FORMAT_INVALID) { MMCAM_LOG_ERROR("Unsupported pixel type"); MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL); @@ -1366,7 +1698,7 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstSample *sampl if (sample3 && mapinfo3.data && mapinfo3.size != 0) { MMCAM_LOG_INFO("Screennail (sample3=%p,size=%zu)", sample3, mapinfo3.size); - pixtype_scrnl = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample3)); + pixtype_scrnl = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample3), FALSE); __mmcamcorder_get_capture_data_from_buffer(&scrnail, pixtype_scrnl, sample3); /* Set screennail attribute for application */ @@ -1389,7 +1721,7 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstSample *sampl /* Thumbnail image buffer */ if (sample2 && mapinfo2.data && (mapinfo2.size != 0)) { MMCAM_LOG_INFO("Thumbnail (buffer2=%p)", gst_sample_get_buffer(sample2)); - pixtype_thumb = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample2)); + pixtype_thumb = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample2), FALSE); __mmcamcorder_get_capture_data_from_buffer(&thumb, pixtype_thumb, sample2); } else { MMCAM_LOG_INFO("Sample2 has wrong pointer. Not Error. (sample2 %p)", sample2); @@ -1792,7 +2124,36 @@ static void __mmcamcorder_extra_preview_stream_cb(GstElement *element, int strea } -gboolean __mmcamcorder_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data) +static gboolean __mmcamcorder_handoff_callback_extra_preview(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data) +{ + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); + _MMCamcorderSubContext *sc = NULL; + + GstCaps *caps = NULL; + GstSample *sample = NULL; + + mmf_return_val_if_fail(hcamcorder, FALSE); + + sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); + mmf_return_val_if_fail(sc && sc->element, FALSE); + + /* make sample with buffer and caps */ + caps = gst_pad_get_allowed_caps(pad); + mmf_return_val_if_fail(caps, TRUE); + + sample = gst_sample_new(buffer, caps, NULL, NULL); + gst_caps_unref(caps); + mmf_return_val_if_fail(sample, TRUE); + + _mmcamcorder_invoke_video_stream_cb((MMHandleType)u_data, sample, TRUE, 0); + + gst_sample_unref(sample); + + return TRUE; +} + + +static gboolean __mmcamcorder_handoff_callback_capture(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); _MMCamcorderSubContext *sc = NULL; @@ -2148,7 +2509,7 @@ exit: } -int __mmcamcorder_update_exif_info(MMHandleType handle, void* imagedata, int imgln) +static int __mmcamcorder_update_exif_info(MMHandleType handle, void* imagedata, int imgln) { int ret = MM_ERROR_NONE; mmf_camcorder_t *hcamcorder = NULL; @@ -2182,7 +2543,7 @@ int __mmcamcorder_update_exif_info(MMHandleType handle, void* imagedata, int img return ret; } -int __mmcamcorder_set_exif_basic_info(MMHandleType handle, int image_width, int image_height) +static int __mmcamcorder_set_exif_basic_info(MMHandleType handle, int image_width, int image_height) { int ret = MM_ERROR_NONE; int value; @@ -2918,7 +3279,7 @@ exit: } -static void __sound_status_changed_cb(keynode_t* node, void *data) +static void __mmcamcorder_sound_status_changed_cb(keynode_t* node, void *data) { mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data; _MMCamcorderImageInfo *info = NULL; @@ -2937,28 +3298,63 @@ static void __sound_status_changed_cb(keynode_t* node, void *data) } -int _mmcamcorder_set_extra_preview_stream_format(MMHandleType camcorder, int stream_id, int pixel_format, int width, int height, int fps) +int _mmcamcorder_set_extra_preview_device_type(MMHandleType handle, int stream_id, int device_type) +{ + int ret = MM_ERROR_NONE; + int camera_id = 0; + mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle; + MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE; + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + mmf_return_val_if_fail(hcamcorder->extra_preview.mode == MM_CAMCORDER_EXTRA_PREVIEW_MODE_PIPELINE_ELEMENT, + MM_ERROR_CAMCORDER_NOT_SUPPORTED); + mmf_return_val_if_fail(stream_id >= 0 && stream_id < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_MAX, + MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(device_type > MM_VIDEO_DEVICE_NONE && device_type < MM_VIDEO_DEVICE_NUM + , MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + mm_camcorder_get_state(handle, ¤t_state); + + MMCAM_LOG_INFO("stream_id[%d], device type[%d]", stream_id, device_type); + + if (current_state > MM_CAMCORDER_STATE_NULL) { + MMCAM_LOG_ERROR("The device type can not be set after pipeline created"); + return MM_ERROR_CAMCORDER_INVALID_STATE; + } + + ret = _mmcamcorder_get_camera_id(device_type, &camera_id); + if (ret != MM_ERROR_NONE) + return ret; + + hcamcorder->extra_preview.camera_id[stream_id] = camera_id; + + return MM_ERROR_NONE; +} + + +int _mmcamcorder_set_extra_preview_stream_format(MMHandleType handle, int stream_id, int pixel_format, int width, int height, int fps) { - mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)camcorder; + mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle; MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE; GstCameraControl *control = NULL; _MMCamcorderSubContext *sc = NULL; mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); - mmf_return_val_if_fail(hcamcorder->support_extra_preview, MM_ERROR_CAMCORDER_NOT_SUPPORTED); - mmf_return_val_if_fail(stream_id >= 0 && stream_id < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_NUM, + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + mmf_return_val_if_fail(stream_id >= 0 && stream_id < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_MAX, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); mmf_return_val_if_fail(pixel_format > MM_PIXEL_FORMAT_INVALID && pixel_format < MM_PIXEL_FORMAT_NUM, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); mmf_return_val_if_fail(width > 0 && height > 0 && fps >= 0, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); - mm_camcorder_get_state(camcorder, ¤t_state); + mm_camcorder_get_state(handle, ¤t_state); MMCAM_LOG_INFO("state[%d] stream_id[%d],fmt[%d],res[%dx%d],fps[%d]", current_state, stream_id, pixel_format, width, height, fps); if (current_state >= MM_CAMCORDER_STATE_READY) { - sc = MMF_CAMCORDER_SUBCONTEXT(camcorder); + sc = MMF_CAMCORDER_SUBCONTEXT(handle); mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); @@ -2969,37 +3365,37 @@ int _mmcamcorder_set_extra_preview_stream_format(MMHandleType camcorder, int str } } else { MMCAM_LOG_INFO("It will be set when start preview"); + hcamcorder->extra_preview.format[stream_id].need_to_set_format = TRUE; } - hcamcorder->extra_preview_format[stream_id].pixel_format = pixel_format; - hcamcorder->extra_preview_format[stream_id].width = width; - hcamcorder->extra_preview_format[stream_id].height = height; - hcamcorder->extra_preview_format[stream_id].fps = fps; - hcamcorder->extra_preview_format[stream_id].is_set = TRUE; + hcamcorder->extra_preview.format[stream_id].pixel_format = pixel_format; + hcamcorder->extra_preview.format[stream_id].width = width; + hcamcorder->extra_preview.format[stream_id].height = height; + hcamcorder->extra_preview.format[stream_id].fps = fps; return MM_ERROR_NONE; } -int _mmcamcorder_get_extra_preview_stream_format(MMHandleType camcorder, int stream_id, int *pixel_format, int *width, int *height, int *fps) +int _mmcamcorder_get_extra_preview_stream_format(MMHandleType handle, int stream_id, int *pixel_format, int *width, int *height, int *fps) { int _width = 0; int _height = 0; int _fps = 0; GstCameraControlImageFormat _img_fmt = GST_CAMERA_CONTROL_IMAGE_FORMAT_NV12; GstCameraControl *control = NULL; - mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)camcorder; + mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle; MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE; _MMCamcorderSubContext *sc = NULL; mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); - mmf_return_val_if_fail(hcamcorder->support_extra_preview, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); mmf_return_val_if_fail(pixel_format && width && height && fps, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); - mm_camcorder_get_state(camcorder, ¤t_state); + mm_camcorder_get_state(handle, ¤t_state); if (current_state >= MM_CAMCORDER_STATE_READY) { - sc = MMF_CAMCORDER_SUBCONTEXT(camcorder); + sc = MMF_CAMCORDER_SUBCONTEXT(handle); mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); @@ -3014,10 +3410,10 @@ int _mmcamcorder_get_extra_preview_stream_format(MMHandleType camcorder, int str *height = _height; *fps = _fps; } else { - *pixel_format = hcamcorder->extra_preview_format[stream_id].pixel_format; - *width = hcamcorder->extra_preview_format[stream_id].width; - *height = hcamcorder->extra_preview_format[stream_id].height; - *fps = hcamcorder->extra_preview_format[stream_id].fps; + *pixel_format = hcamcorder->extra_preview.format[stream_id].pixel_format; + *width = hcamcorder->extra_preview.format[stream_id].width; + *height = hcamcorder->extra_preview.format[stream_id].height; + *fps = hcamcorder->extra_preview.format[stream_id].fps; } MMCAM_LOG_INFO("get result[fmt:%d(%d),res:%dx%d,fps:%d][state:%d]", @@ -3025,3 +3421,152 @@ int _mmcamcorder_get_extra_preview_stream_format(MMHandleType camcorder, int str return MM_ERROR_NONE; } + + +int _mmcamcorder_set_extra_preview_bitrate(MMHandleType handle, int stream_id, int bitrate) +{ + mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle; + MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE; + GstCameraControl *control = NULL; + _MMCamcorderSubContext *sc = NULL; + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + mmf_return_val_if_fail(stream_id >= 0 && stream_id < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_MAX, + MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(bitrate > 0, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + mm_camcorder_get_state(handle, ¤t_state); + + MMCAM_LOG_INFO("state[%d] stream[%d], bitrate[%d]", current_state, stream_id, bitrate); + + if (current_state >= MM_CAMCORDER_STATE_READY) { + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + if (!gst_camera_control_set_extra_preview_bitrate(control, stream_id, bitrate)) { + MMCAM_LOG_ERROR("set bitrate[%d] for stream[%d] failed", bitrate, stream_id); + return MM_ERROR_CAMCORDER_INTERNAL; + } + } else { + MMCAM_LOG_INFO("It will be set when start preview"); + hcamcorder->extra_preview.format[stream_id].need_to_set_bitrate = TRUE; + } + + hcamcorder->extra_preview.format[stream_id].bitrate = bitrate; + + return MM_ERROR_NONE; +} + + +int _mmcamcorder_get_extra_preview_bitrate(MMHandleType handle, int stream_id, int *bitrate) +{ + int _bitrate = 0; + GstCameraControl *control = NULL; + mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle; + MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE; + _MMCamcorderSubContext *sc = NULL; + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + mmf_return_val_if_fail(stream_id >= 0 && stream_id < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_MAX, + MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(bitrate, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + mm_camcorder_get_state(handle, ¤t_state); + + if (current_state >= MM_CAMCORDER_STATE_READY) { + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + if (!gst_camera_control_get_extra_preview_bitrate(control, stream_id, &_bitrate)) { + MMCAM_LOG_ERROR("get bitrate for stream[%d] failed", stream_id); + return MM_ERROR_CAMCORDER_INTERNAL; + } + + *bitrate = _bitrate; + } else { + *bitrate = hcamcorder->extra_preview.format[stream_id].bitrate; + } + + MMCAM_LOG_INFO("get bitrate[%d] for stream[%d][state:%d]", + *bitrate, stream_id, current_state); + + return MM_ERROR_NONE; +} + + +int _mmcamcorder_set_extra_preview_gop_interval(MMHandleType handle, int stream_id, int interval) +{ + mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle; + MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE; + GstCameraControl *control = NULL; + _MMCamcorderSubContext *sc = NULL; + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + mmf_return_val_if_fail(stream_id >= 0 && stream_id < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_MAX, + MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + mm_camcorder_get_state(handle, ¤t_state); + + MMCAM_LOG_INFO("state[%d] stream[%d], interval[%d]", current_state, stream_id, interval); + + if (current_state >= MM_CAMCORDER_STATE_READY) { + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + if (!gst_camera_control_set_extra_preview_gop_interval(control, stream_id, interval)) { + MMCAM_LOG_ERROR("set GOP interval[%d] for stream[%d] failed", interval, stream_id); + return MM_ERROR_CAMCORDER_INTERNAL; + } + } else { + MMCAM_LOG_INFO("It will be set when start preview"); + hcamcorder->extra_preview.format[stream_id].need_to_set_gop_interval = TRUE; + } + + hcamcorder->extra_preview.format[stream_id].gop_interval = interval; + + return MM_ERROR_NONE; +} + + +int _mmcamcorder_get_extra_preview_gop_interval(MMHandleType handle, int stream_id, int *interval) +{ + int _interval = 0; + GstCameraControl *control = NULL; + mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle; + MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE; + _MMCamcorderSubContext *sc = NULL; + + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(hcamcorder->extra_preview.is_supported, MM_ERROR_CAMCORDER_NOT_SUPPORTED); + mmf_return_val_if_fail(stream_id >= 0 && stream_id < MM_CAMCORDER_EXTRA_PREVIEW_STREAM_MAX, + MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + mmf_return_val_if_fail(interval, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + mm_camcorder_get_state(handle, ¤t_state); + + if (current_state >= MM_CAMCORDER_STATE_READY) { + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_INVALID_ARGUMENT); + + control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + if (!gst_camera_control_get_extra_preview_gop_interval(control, stream_id, &_interval)) { + MMCAM_LOG_ERROR("get GOP interval for stream[%d] failed", stream_id); + return MM_ERROR_CAMCORDER_INTERNAL; + } + + *interval = _interval; + } else { + *interval = hcamcorder->extra_preview.format[stream_id].gop_interval; + } + + MMCAM_LOG_INFO("get GOP interval[%d] for stream[%d][state:%d]", + *interval, stream_id, current_state); + + return MM_ERROR_NONE; +}