From: Jeongmo Yang Date: Tue, 17 May 2016 06:44:10 +0000 (+0900) Subject: [Release version 0.10.49] Update code for encoded preview format X-Git-Tag: submit/tizen/20160524.060031~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5b6c0e69c7a7784c714cce8d84f6cdac958c6c3b;p=platform%2Fcore%2Fmultimedia%2Flibmm-camcorder.git [Release version 0.10.49] Update code for encoded preview format Change-Id: I2457572318b41b976992b425a4337b3ed32667a6 Signed-off-by: Jeongmo Yang --- diff --git a/packaging/libmm-camcorder.spec b/packaging/libmm-camcorder.spec index 104dfe2..bfa9552 100644 --- a/packaging/libmm-camcorder.spec +++ b/packaging/libmm-camcorder.spec @@ -2,7 +2,7 @@ Name: libmm-camcorder Summary: Camera and recorder library -Version: 0.10.48 +Version: 0.10.49 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/include/mm_camcorder_gstcommon.h b/src/include/mm_camcorder_gstcommon.h index bb74829..3ee896d 100644 --- a/src/include/mm_camcorder_gstcommon.h +++ b/src/include/mm_camcorder_gstcommon.h @@ -150,6 +150,7 @@ int _mmcamcorder_create_preview_pipeline(MMHandleType handle); /* plug-in related */ void _mmcamcorder_ready_to_encode_callback(GstElement *element, guint size, gpointer handle); +bool _mmcamcorder_recreate_decoder_for_encoded_preview(MMHandleType handle); /* etc */ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element *VideosinkElement); diff --git a/src/include/mm_camcorder_internal.h b/src/include/mm_camcorder_internal.h index 1340fac..6e6982b 100644 --- a/src/include/mm_camcorder_internal.h +++ b/src/include/mm_camcorder_internal.h @@ -626,6 +626,7 @@ typedef struct { type_element *VideosinkElement; /**< configure data of videosink element */ type_element *VideoconvertElement; /**< configure data of videoconvert element */ + type_element *VideodecoderElementH264; /**< configure data of video decoder element for H.264 format */ gboolean SensorEncodedCapture; /**< whether camera sensor support encoded image capture */ gboolean internal_encode; /**< whether use internal encoding function */ } _MMCamcorderSubContext; @@ -697,6 +698,7 @@ typedef struct mmf_camcorder { int acquired_focus; /**< Current acquired focus */ int session_type; /**< Session type */ int session_flags; /**< Session flags */ + int recreate_decoder; /**< Flag of decoder element recreation for encoded preview format */ _MMCamcorderInfoConverting caminfo_convert[CAMINFO_CONVERT_NUM]; /**< converting structure of camera info */ _MMCamcorderEnumConvert enum_conv[ENUM_CONVERT_NUM]; /**< enum converting list that is modified by ini info */ diff --git a/src/mm_camcorder_attribute.c b/src/mm_camcorder_attribute.c index 7e7a382..01526fd 100644 --- a/src/mm_camcorder_attribute.c +++ b/src/mm_camcorder_attribute.c @@ -2222,6 +2222,13 @@ bool _mmcamcorder_commit_camera_width(MMHandleType handle, int attr_idx, const m _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + /* check decoder recreation */ + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed"); + g_mutex_unlock(&hcamcorder->restart_preview_lock); + return FALSE; + } + /* get preview format */ sc->info_image->preview_format = preview_format; sc->fourcc = _mmcamcorder_get_fourcc(sc->info_image->preview_format, codec_type, hcamcorder->use_zero_copy_format); @@ -2312,6 +2319,13 @@ bool _mmcamcorder_commit_camera_height(MMHandleType handle, int attr_idx, const _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + /* check decoder recreation */ + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed"); + g_mutex_unlock(&hcamcorder->restart_preview_lock); + return FALSE; + } + /* get preview format */ sc->info_image->preview_format = preview_format; sc->fourcc = _mmcamcorder_get_fourcc(sc->info_image->preview_format, codec_type, hcamcorder->use_zero_copy_format); @@ -4142,6 +4156,12 @@ bool _mmcamcorder_commit_camera_hdr_capture(MMHandleType handle, int attr_idx, c _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + /* check decoder recreation */ + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed"); + return FALSE; + } + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); } diff --git a/src/mm_camcorder_configure.c b/src/mm_camcorder_configure.c index b573b17..2b51068 100644 --- a/src/mm_camcorder_configure.c +++ b/src/mm_camcorder_configure.c @@ -175,6 +175,16 @@ void _mmcamcorder_conf_init(MMHandleType handle, int type, camera_conf** configu 0, }; + /* H.264 decoder element default value */ + static type_element _videodecoder_element_h264_default = { + "VideodecoderElementH264", + "avdec_h264", + NULL, + 0, + NULL, + 0, + }; + /* Record sink element default value */ static type_element _recordsink_element_default = { "RecordsinkElement", @@ -646,6 +656,8 @@ void _mmcamcorder_conf_init(MMHandleType handle, int type, camera_conf** configu { "UseVideoscale", CONFIGURE_VALUE_INT, {.value_int = 0} }, { "VideoscaleElement", CONFIGURE_VALUE_ELEMENT, {&_videoscale_element_default} }, { "VideoconvertElement", CONFIGURE_VALUE_ELEMENT, {&_videoconvert_element_default} }, + { "VideodecoderElementH264", CONFIGURE_VALUE_ELEMENT, {&_videodecoder_element_h264_default} }, + { "RecreateDecoder", CONFIGURE_VALUE_INT, {.value_int = 0} } }; /* [Capture] matching table */ diff --git a/src/mm_camcorder_gstcommon.c b/src/mm_camcorder_gstcommon.c index 964703d..8fa89c2 100644 --- a/src/mm_camcorder_gstcommon.c +++ b/src/mm_camcorder_gstcommon.c @@ -132,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" /*----------------------------------------------------------------------- @@ -293,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, @@ -305,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); @@ -2606,3 +2630,113 @@ bool _mmcamcorder_set_sound_stream_info(GstElement *element, char *stream_type, 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; +} diff --git a/src/mm_camcorder_stillshot.c b/src/mm_camcorder_stillshot.c index fe750c9..1b7d20b 100644 --- a/src/mm_camcorder_stillshot.c +++ b/src/mm_camcorder_stillshot.c @@ -440,6 +440,12 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) /* make pipeline state as READY */ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + /* check decoder recreation */ + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed"); + return MM_ERROR_CAMCORDER_INTERNAL; + } + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); @@ -699,9 +705,18 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) if (info->resolution_change) { MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE); + ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY); + + /* check decoder recreation */ + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed"); + return MM_ERROR_CAMCORDER_INTERNAL; + } + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); + if (ret != MM_ERROR_NONE) { goto cmd_error; } diff --git a/src/mm_camcorder_videorec.c b/src/mm_camcorder_videorec.c index b7b5834..c70ff38 100644 --- a/src/mm_camcorder_videorec.c +++ b/src/mm_camcorder_videorec.c @@ -639,6 +639,13 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY); + /* check decoder recreation */ + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed"); + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_CAMCORDER_VIDEO_COMMAND; + } + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); @@ -927,8 +934,15 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY); + /* check decoder recreation */ + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed"); + ret = MM_ERROR_CAMCORDER_INTERNAL; + } + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); + if (ret != MM_ERROR_NONE) { goto _ERR_CAMCORDER_VIDEO_COMMAND; } @@ -1184,6 +1198,12 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle) _mmcam_dbg_log("Set state of pipeline as READY"); ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + /* check decoder recreation */ + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed"); + ret = MM_ERROR_CAMCORDER_INTERNAL; + } + /* unblock queue */ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);