Name: libmm-camcorder
Summary: Camera and recorder library
-Version: 0.10.264
+Version: 0.10.265
Release: 0
Group: Multimedia/Libraries
License: Apache-2.0
/**
- * An enumeration of Audio Format.
+ * An enumeration of audio format.
*/
typedef enum {
MM_CAMCORDER_AUDIO_FORMAT_PCM_U8 = 0, /**< unsigned 8bit audio */
MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE = 2, /**< signed 16bit audio. Little endian. */
} MMCamcorderAudioFormat;
+/**
+ * An enumeration of capture mode.
+ */
+typedef enum {
+ MM_CAMCORDER_CAPTURE_MODE_ENCODEBIN = 0, /**< Capture through encodebin */
+ MM_CAMCORDER_CAPTURE_MODE_CAMERA_CONTROL, /**< Capture through camera control interface in camerasrc plugin */
+ MM_CAMCORDER_CAPTURE_MODE_IMAGE_PAD /**< Capture through image source pad in camerasrc plugin */
+} MMCamcorderCaptureMode;
+
/**
* An enumeration for color tone. Color tone provides an impression of
/* Pipeline element of Video input */
_MMCAMCORDER_VIDEOSRC_SRC,
_MMCAMCORDER_VIDEOSRC_FILT,
- _MMCAMCORDER_VIDEOSRC_CLS_QUE,
- _MMCAMCORDER_VIDEOSRC_CLS,
- _MMCAMCORDER_VIDEOSRC_CLS_FILT,
_MMCAMCORDER_VIDEOSRC_QUE,
_MMCAMCORDER_VIDEOSRC_DECODE,
+ /* Pipeline element of image capture */
+ _MMCAMCORDER_VIDEOSRC_CAP_FILT,
+ _MMCAMCORDER_VIDEOSRC_CAP_SINK,
+
/* Pipeline element of Video output */
_MMCAMCORDER_VIDEOSINK_QUE,
_MMCAMCORDER_VIDEOSINK_CLS,
GstClockTime previous_slot_time;
int display_interval; /**< This value is set as 'GST_SECOND / display FPS' */
gboolean bget_eos; /**< Whether getting EOS */
- gboolean bencbin_capture; /**< Use Encodebin for capturing */
gboolean audio_disable; /**< whether audio is disabled or not when record */
int videosrc_rotate; /**< rotate of videosrc */
unsigned long long muxed_stream_offset; /**< current offset for muxed stream data */
int use_videoconvert; /**< Whether use videoconvert element for display */
int support_media_packet_preview_cb; /**< Whether support zero copy format for camera input */
int support_user_buffer; /**< Whether support user allocated buffer for zero copy */
+ int capture_mode; /**< Capture mode */
int shutter_sound_policy; /**< shutter sound policy */
int brightness_default; /**< default value of brightness */
int brightness_step_denominator; /**< denominator of brightness bias step */
/*=======================================================================================
| GLOBAL FUNCTION PROTOTYPES |
========================================================================================*/
-/**
- * This function add still shot bin to main pipeline.
- * When application creates initial pipeline, there are only bins for preview.
- * If application wants to add still shot function, bins for stillshot should be added.
- *
- * @param[in] handle Handle of camcorder context.
- * @return This function returns MM_ERROR_NONE on success, or the other values on error.
- * @remarks
- * @see __mmcamcorder_create_preview_pipeline()
- */
-int _mmcamcorder_create_stillshot_pipeline(MMHandleType handle);
-
-/**
- * This function remove still shot bin from main pipeline.
- *
- * @param[in] handle Handle of camcorder context.
- * @return This function returns MM_ERROR_NONE on success, or the other values on error.
- * @remarks
- * @see __mmcamcorder_create_preview_pipeline(), __mmcamcorder_add_stillshot_pipeline()
- */
-int _mmcamcorder_remove_stillshot_pipeline(MMHandleType handle);
+int _mmcamcorder_prepare_capture_mode_camera_control(MMHandleType handle);
+int _mmcamcorder_prepare_capture_mode_encodebin(MMHandleType handle);
+int _mmcamcorder_prepare_capture_mode_image_pad(MMHandleType handle);
-/**
- * This function connects capture signal.
- *
- * @param[in] handle Handle of camcorder context.
- * @return This function returns MM_ERROR_NONE on success, or the other values on error.
- * @remarks
- */
-int _mmcamcorder_connect_capture_signal(MMHandleType handle);
+int _mmcamcorder_unprepare_capture_mode_encodebin(MMHandleType handle);
/**
* This function destroy image pipeline.
/* [Capture] matching table */
static conf_info_table conf_main_capture_table[] = {
- { "UseEncodebin", CONFIGURE_VALUE_INT, {.value_int = 0} },
+ { "CaptureMode", CONFIGURE_VALUE_INT, {.value_int = MM_CAMCORDER_CAPTURE_MODE_ENCODEBIN} },
{ "VideoscaleElement", CONFIGURE_VALUE_ELEMENT, {&_videoscale_element_default} },
{ "PlayCaptureSound", CONFIGURE_VALUE_INT, {.value_int = 1} },
};
int codectype = 0;
int capture_width = 0;
int capture_height = 0;
- int capture_jpg_quality = 100;
+ int capture_quality = 0;
int video_stabilization = 0;
int anti_shake = 0;
int display_surface_type = MM_DISPLAY_SURFACE_NULL;
MMCAM_CAPTURE_HEIGHT, &capture_height,
MMCAM_CAMERA_HDR_CAPTURE, &sc->info_image->hdr_capture_mode,
MMCAM_IMAGE_ENCODER, &codectype,
- MMCAM_IMAGE_ENCODER_QUALITY, &capture_jpg_quality,
+ MMCAM_IMAGE_ENCODER_QUALITY, &capture_quality,
MMCAM_DISPLAY_SURFACE, &display_surface_type,
MMCAM_EXTRA_PREVIEW_ENABLE, &extra_preview_enable,
NULL);
MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "high-speed-fps", 0);
MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-width", capture_width);
MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-height", capture_height);
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-jpg-quality", capture_jpg_quality);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-quality", capture_quality);
MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hdr-capture", sc->info_image->hdr_capture_mode);
MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "extra-preview", extra_preview_enable);
MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "buffer-quark", &hcamcorder->buffer_quark);
pipeline_creation_error:
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_SRC);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_FILT);
- _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CLS_QUE);
- _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CLS);
- _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CLS_FILT);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_QUE);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CAP_FILT);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CAP_SINK);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_DECODE);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSINK_QUE);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSINK_SINK);
_mmcamcorder_conf_get_value_int((MMHandleType)hcamcorder, hcamcorder->conf_main,
CONFIGURE_CATEGORY_MAIN_CAPTURE,
+ "CaptureMode",
+ &hcamcorder->capture_mode);
+
+ _mmcamcorder_conf_get_value_int((MMHandleType)hcamcorder, hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_CAPTURE,
"PlayCaptureSound",
&play_capture_sound);
MMCAM_LOG_INFO("Support user buffer[%d]", hcamcorder->support_user_buffer);
MMCAM_LOG_INFO("Support media packet preview cb[%d]", hcamcorder->support_media_packet_preview_cb);
MMCAM_LOG_INFO("Support extra preview[%d]", hcamcorder->support_extra_preview);
+ MMCAM_LOG_INFO("Capture mode[%d]", hcamcorder->capture_mode);
MMCAM_LOG_INFO("Use zero copy format[%d]", hcamcorder->use_zero_copy_format);
MMCAM_LOG_INFO("Use video convert[%d]", hcamcorder->use_videoconvert);
MMCAM_LOG_INFO("Measure preview FPS[%d]", hcamcorder->measure_preview_fps);
if (motion_rate != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE)
hcamcorder->sub_context->is_modified_rate = TRUE;
- _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
- CONFIGURE_CATEGORY_MAIN_CAPTURE,
- "UseEncodebin",
- &(hcamcorder->sub_context->bencbin_capture));
- MMCAM_LOG_WARNING("UseEncodebin [%d]", hcamcorder->sub_context->bencbin_capture);
-
if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) {
/* get video recording info */
_mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
if (ret != MM_ERROR_NONE)
return ret;
- if (!sc->bencbin_capture) {
- ret = _mmcamcorder_connect_capture_signal(handle);
+ if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_CAMERA_CONTROL) {
+ ret = _mmcamcorder_prepare_capture_mode_camera_control(handle);
+ if (ret != MM_ERROR_NONE)
+ return ret;
+ } else if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_IMAGE_PAD) {
+ ret = _mmcamcorder_prepare_capture_mode_image_pad(handle);
if (ret != MM_ERROR_NONE)
return ret;
}
---------------------------------------------------------------------------------------*/
-int _mmcamcorder_create_stillshot_pipeline(MMHandleType handle)
+int _mmcamcorder_prepare_capture_mode_encodebin(MMHandleType handle)
{
int err = MM_ERROR_UNKNOWN;
GstPad *srcpad = NULL;
return MM_ERROR_NONE;
pipeline_creation_error:
- _mmcamcorder_remove_stillshot_pipeline(handle);
+ _mmcamcorder_unprepare_capture_mode_encodebin(handle);
return err;
}
-int _mmcamcorder_connect_capture_signal(MMHandleType handle)
+int _mmcamcorder_prepare_capture_mode_camera_control(MMHandleType handle)
{
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
_MMCamcorderSubContext *sc = NULL;
}
+int _mmcamcorder_prepare_capture_mode_image_pad(MMHandleType handle)
+{
+ 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;
+
+ 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_FILT, "capsfilter", "videosrc_cap_filt", element_list, err);
+ _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_CAP_SINK, "fakesink", "videosrc_cap_sink", 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_FILT].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_FILT].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),
+ hcamcorder);
+
+ return MM_ERROR_NONE;
+
+pipeline_creation_error:
+ _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CAP_FILT);
+ _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_extra_preview_stream(MMHandleType handle)
{
int i = 0;
}
-int _mmcamcorder_remove_stillshot_pipeline(MMHandleType handle)
+int _mmcamcorder_unprepare_capture_mode_encodebin(MMHandleType handle)
{
int ret = MM_ERROR_NONE;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(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;
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) ||
info->resolution_change = FALSE;
}
- /* add encodesinkbin */
- ret = _mmcamcorder_create_stillshot_pipeline((MMHandleType)hcamcorder);
+ ret = _mmcamcorder_prepare_capture_mode_encodebin((MMHandleType)hcamcorder);
if (ret != MM_ERROR_NONE) {
MMCAM_LOG_ERROR("failed to create encodesinkbin %x", ret);
goto cmd_done;
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 */
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) {
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_unprepare_capture_mode_encodebin(handle);
if (ret != MM_ERROR_NONE)
goto cmd_error;
}
} else {
/* for image capture with encodebin and v4l2src */
- if (sc->bencbin_capture && info_image->capturing) {
+ if (hcamcorder->capture_mode == MM_CAMCORDER_CAPTURE_MODE_ENCODEBIN && info_image->capturing) {
g_mutex_lock(&hcamcorder->task_thread_lock);
MMCAM_LOG_INFO("send signal for sound play");
hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_SOUND_SOLO_PLAY_START;