Bug fix - Recording is failed without setting filename 95/131995/1 accepted/tizen/unified/20170612.073910 submit/tizen/20170612.030116
authorJeongmo Yang <jm80.yang@samsung.com>
Wed, 31 May 2017 12:14:25 +0000 (21:14 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Wed, 31 May 2017 12:14:25 +0000 (21:14 +0900)
Recording should not be failed if muxed stream callback is set
although file name is not set, but it's failed because of bug.
This patch will fix it and update code for setting recording file name
and fixing encodebin's sink element as filesink.(fakesink is only used for image capture.)

[Version] 0.10.122
[Profile] Common
[Issue Type] Bug fix
[Dependency module] N/A
[Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-unified_20170524.4]

Change-Id: I786266d69c450d1cf6bf4ab75e4defb477abb9f3
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
packaging/libmm-camcorder.spec
src/include/mm_camcorder_internal.h
src/mm_camcorder_attribute.c
src/mm_camcorder_audiorec.c
src/mm_camcorder_gstcommon.c
src/mm_camcorder_internal.c
src/mm_camcorder_util.c
src/mm_camcorder_videorec.c

index 8d5db25..c0642e4 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-camcorder
 Summary:    Camera and recorder library
-Version:    0.10.121
+Version:    0.10.122
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 5117b99..d944dac 100644 (file)
@@ -316,6 +316,11 @@ extern "C" {
 #define _MMCamcorder_FILENAME_LEN      (512)
 
 /**
+ *     File name for NULL path
+ */
+#define _MMCamcorder_FILENAME_NULL     "/dev/null"
+
+/**
  *     Minimum integer value
  */
 #define _MMCAMCORDER_MIN_INT   (INT_MIN)
index 70b608a..bc6799e 100644 (file)
@@ -3389,20 +3389,11 @@ bool _mmcamcorder_commit_image_encoder_quality(MMHandleType handle, int attr_idx
 
 bool _mmcamcorder_commit_target_filename(MMHandleType handle, int attr_idx, const mmf_value_t *value)
 {
-       int ret = MM_ERROR_NONE;
        int size = 0;
        const char *filename = NULL;
-       _MMCamcorderSubContext *sc = NULL;
-       GstElement *encode_link = NULL;
-       GstElement *encode_sink = NULL;
-       GstElement *encode_pipeline = NULL;
 
        mmf_return_val_if_fail(handle && value, FALSE);
 
-       sc = MMF_CAMCORDER_SUBCONTEXT(handle);
-       if (!sc)
-               return TRUE;
-
        /* get string */
        filename = mmf_value_get_string(value, &size);
        if (filename == NULL) {
@@ -3410,84 +3401,7 @@ bool _mmcamcorder_commit_target_filename(MMHandleType handle, int attr_idx, cons
                return FALSE;
        }
 
-       if (sc->info_video) {
-               SAFE_G_FREE(sc->info_video->filename);
-               sc->info_video->filename = g_strdup(filename);
-               if (sc->info_video->filename == NULL) {
-                       _mmcam_dbg_err("failed to strdup filename [%s]", filename);
-                       return FALSE;
-               }
-       }
-
-       if (sc->encode_element && sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst) {
-               encode_sink = sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst;
-               encode_pipeline = sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst;
-
-               _mmcam_dbg_log("file location set.[%s], current encode sink [%s]",
-                       filename, GST_OBJECT_NAME(gst_element_get_factory(encode_sink)));
-
-               /* check whether it's filesink or not */
-               if (strncmp(GST_OBJECT_NAME(gst_element_get_factory(encode_sink)), "filesink", strlen("filesink"))) {
-                       _mmcam_dbg_log("remove current sink and create filesink");
-
-                       /* remove fakesink and create/add filesink to encode pipeline */
-                       /* set NULL state */
-                       ret = _mmcamcorder_gst_set_state(handle, encode_sink, GST_STATE_NULL);
-                       if (ret != MM_ERROR_NONE) {
-                               _mmcam_dbg_err("failed to set NULL encoder sink");
-                               return FALSE;
-                       }
-
-                       /* remove encode sink - pads will be unlinked automatically in remove function */
-                       if (!gst_bin_remove(GST_BIN(encode_pipeline), encode_sink)) {
-                               _mmcam_dbg_err("failed to remove encode sink from pipeline");
-                               return FALSE;
-                       }
-
-                       _mmcam_dbg_log("remove done");
-
-                       /* create filesink */
-                       encode_sink = gst_element_factory_make("filesink", NULL);
-                       if (!encode_sink) {
-                               _mmcam_dbg_err("filesink creation failed");
-                               return FALSE;
-                       }
-
-                       sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst = encode_sink;
-
-                       /* set release notification callback */
-                       g_object_weak_ref(G_OBJECT(encode_sink), (GWeakNotify)_mmcamcorder_element_release_noti, sc);
-
-                       /* add to pipeline */
-                       if (!gst_bin_add(GST_BIN(encode_pipeline), encode_sink)) {
-                               _mmcam_dbg_err("failed to add filesink to encode pipeline");
-                               gst_object_unref(encode_sink);
-                               return FALSE;
-                       }
-
-                       /* link filesink */
-                       if (sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst) {
-                               /* mux element is used */
-                               _mmcam_dbg_log("Link mux to encode_sink");
-                               encode_link = sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst;
-                       } else {
-                               /* no mux element */
-                               _mmcam_dbg_log("Link audio encoder to encode_sink");
-                               encode_link = sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst;
-                       }
-
-                       if (!_MM_GST_ELEMENT_LINK(encode_link, encode_sink)) {
-                               _mmcam_dbg_err("Link FAILED");
-                               return FALSE;
-                       }
-
-                       _mmcam_dbg_log("Link OK");
-               }
-
-               MMCAMCORDER_G_OBJECT_SET_POINTER(encode_sink, "location", filename);
-       } else {
-               _mmcam_dbg_log("element is not created yet. [%s] will be set later...", filename);
-       }
+       _mmcam_dbg_log("set filename [%s]", filename);
 
        return TRUE;
 }
index b87a898..14b2337 100644 (file)
@@ -35,8 +35,7 @@
 |    LOCAL VARIABLE DEFINITIONS for internal                                           |
 ---------------------------------------------------------------------------------------*/
 #define RESET_PAUSE_TIME                        0
-#define _MMCAMCORDER_AUDIO_MINIMUM_SPACE        (100*1024)
-#define _MMCAMCORDER_AUDIO_MARGIN_SPACE         (1*1024)
+#define _MMCAMCORDER_AUDIO_MINIMUM_SPACE        ((100*1024) + (5*1024))
 #define _MMCAMCORDER_RETRIAL_COUNT              10
 #define _MMCAMCORDER_FRAME_WAIT_TIME            200000 /* micro second */
 #define _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL  10
@@ -78,6 +77,7 @@ static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle)
        _MMCamcorderSubContext *sc = NULL;
        type_element *aenc_elem = NULL;
        type_element *mux_elem = NULL;
+       type_element *sink_elem = NULL;
 
        mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
        sc = MMF_CAMCORDER_SUBCONTEXT(handle);
@@ -158,15 +158,18 @@ static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle)
 
                _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_AENC, aenc_name, NULL, element_list, err);
 
-               if (file_name)
-                       sink_name = "filesink";
-               else
-                       sink_name = "fakesink";
+               _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
+                       CONFIGURE_CATEGORY_MAIN_RECORD,
+                       "RecordsinkElement",
+                       &sink_elem);
+               _mmcamcorder_conf_get_value_element_name(sink_elem, &sink_name);
 
                _mmcam_dbg_log("encode sink : %s", sink_name);
 
                _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_SINK, sink_name, NULL, element_list, err);
 
+               _mmcamcorder_conf_set_value_element_property(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, sink_elem);
+
                /* add elements to encode pipeline */
                if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), element_list)) {
                        _mmcam_dbg_err("add encode elements error.");
@@ -376,16 +379,21 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                                goto _ERR_CAMCORDER_AUDIO_COMMAND;
                        }
 
+                       SAFE_G_FREE(info->filename);
+
                        if (temp_filename) {
                                info->filename = g_strdup(temp_filename);
                                if (!info->filename) {
-                                       _mmcam_dbg_err("STRDUP was failed");
+                                       _mmcam_dbg_err("STRDUP was failed for [%s]", temp_filename);
                                        goto _ERR_CAMCORDER_AUDIO_COMMAND;
                                }
 
-                               _mmcam_dbg_log("Record start : set file name using attribute - %s\n ", info->filename);
+                               _mmcam_dbg_log("Record start : file name [%s]", info->filename);
 
                                MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
+                       } else {
+                               _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
+                               MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
                        }
 
                        sc->ferror_send = FALSE;
@@ -443,9 +451,10 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                                err = -1;
                        }
 
-                       if ((err == -1) || free_space <= (_MMCAMCORDER_AUDIO_MINIMUM_SPACE+(5*1024))) {
+                       if (temp_filename &&
+                               (err == -1 || free_space <= _MMCAMCORDER_AUDIO_MINIMUM_SPACE)) {
                                _mmcam_dbg_err("OUT of STORAGE [err:%d or free space [%" G_GUINT64_FORMAT "] is smaller than [%d]",
-                                       err, free_space, (_MMCAMCORDER_AUDIO_MINIMUM_SPACE+(5*1024)));
+                                       err, free_space, _MMCAMCORDER_AUDIO_MINIMUM_SPACE);
                                return MM_ERROR_OUT_OF_STORAGE;
                        }
                }
index 287a003..4b3b398 100644 (file)
@@ -730,7 +730,6 @@ void _mmcamcorder_set_encoder_bitrate(MMCamcorderEncoderType type, int codec, in
 int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebinProfile profile)
 {
        int err = MM_ERROR_NONE;
-       int file_name_len = 0;
        int channel = 0;
        int audio_enc = 0;
        int v_bitrate = 0;
@@ -749,7 +748,6 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin
        const char *str_aar = NULL;
        const char *str_acs = NULL;
        char *err_name = NULL;
-       char *file_name = NULL;
        const char *videoconvert_name = NULL;
        GstCaps *audio_caps = NULL;
        GstCaps *video_caps = NULL;
@@ -869,7 +867,6 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin
                MMCAM_AUDIO_CHANNEL, &channel,
                MMCAM_VIDEO_ENCODER_BITRATE, &v_bitrate,
                MMCAM_AUDIO_ENCODER_BITRATE, &a_bitrate,
-               MMCAM_TARGET_FILENAME, &file_name, &file_name_len,
                NULL);
 
        if (err != MM_ERROR_NONE) {
@@ -1066,20 +1063,15 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin
        /* Sink */
        if (profile != MM_CAMCORDER_ENCBIN_PROFILE_IMAGE) {
                /* for recording */
-               if (file_name) {
-                       _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
-                               CONFIGURE_CATEGORY_MAIN_RECORD,
-                               "RecordsinkElement",
-                               &RecordsinkElement);
-                       _mmcamcorder_conf_get_value_element_name(RecordsinkElement, &gst_element_rsink_name);
+               _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
+                       CONFIGURE_CATEGORY_MAIN_RECORD,
+                       "RecordsinkElement",
+                       &RecordsinkElement);
+               _mmcamcorder_conf_get_value_element_name(RecordsinkElement, &gst_element_rsink_name);
 
-                       _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_SINK, gst_element_rsink_name, NULL, element_list, err);
+               _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_SINK, gst_element_rsink_name, NULL, element_list, err);
 
-                       _mmcamcorder_conf_set_value_element_property(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, RecordsinkElement);
-               } else {
-                       /* if file_name is not set, add fakesink for muxed stream callback */
-                       _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_SINK, "fakesink", NULL, element_list, err);
-               }
+               _mmcamcorder_conf_set_value_element_property(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, RecordsinkElement);
        } else {
                /* for stillshot */
                _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_SINK, "fakesink", NULL, element_list, err);
index e0a4e73..61db73b 100644 (file)
@@ -1773,7 +1773,6 @@ int _mmcamcorder_record(MMHandleType handle)
 {
        int ret = MM_ERROR_NONE;
        int state = MM_CAMCORDER_STATE_NONE;
-       int audio_disable = FALSE;
        int dpm_mic_state = DPM_ALLOWED;
 
        mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
index 0e6bc3f..cfcaa2d 100644 (file)
@@ -1246,10 +1246,9 @@ MSG_CALLBACK_DONE:
        } else if (item->id == MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED || item->id == MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED) {
                MMCamRecordingReport *report = (MMCamRecordingReport *)item->param.data;
                if (report) {
-                       if (report->recording_filename)
-                               SAFE_G_FREE(report->recording_filename);
-
-                       SAFE_G_FREE(report);
+                       SAFE_G_FREE(report->recording_filename);
+                       g_free(report);
+                       report = NULL;
                        item->param.data = NULL;
                }
        }
index b786e55..5d1f681 100644 (file)
@@ -41,6 +41,7 @@
 #define _MMCAMCORDER_FRAME_WAIT_TIME   200000  /* ms */
 #define _OFFSET_COMPOSITION_MATRIX             40L
 #define _GOP_GEN_INTERVAL                              1000000000      /*nano seconds*/
+#define _MMCAMCORDER_VIDEO_MINIMUM_SPACE       (_MMCAMCORDER_MINIMUM_SPACE << 1)      /* byte */
 
 /*---------------------------------------------------------------------------------------
 |    LOCAL FUNCTION PROTOTYPES:                                                                                                                        |
@@ -621,8 +622,8 @@ int _mmcamcorder_video_command(MMHandleType handle, int command)
                                goto _ERR_CAMCORDER_VIDEO_COMMAND;
                        }
 
-                       if (temp_filename == NULL) {
-                               _mmcam_dbg_err("filename is not set");
+                       if (!temp_filename && !hcamcorder->mstream_cb) {
+                               _mmcam_dbg_err("filename is not set and muxed stream cb is NULL");
                                ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
                                goto _ERR_CAMCORDER_VIDEO_COMMAND;
                        }
@@ -675,9 +676,10 @@ int _mmcamcorder_video_command(MMHandleType handle, int command)
                                ret_free_space = -1;
                        }
 
-                       if ((ret_free_space == -1) || free_space <= (_MMCAMCORDER_MINIMUM_SPACE<<1)) {
+                       if (temp_filename &&
+                               (ret_free_space == -1 || free_space <= _MMCAMCORDER_VIDEO_MINIMUM_SPACE)) {
                                _mmcam_dbg_err("OUT of STORAGE [ret_free_space:%d or free space [%" G_GUINT64_FORMAT "] is smaller than [%d]",
-                                       ret_free_space, free_space, (_MMCAMCORDER_MINIMUM_SPACE<<1));
+                                       ret_free_space, free_space, _MMCAMCORDER_VIDEO_MINIMUM_SPACE);
                                return MM_ERROR_OUT_OF_STORAGE;
                        }
 
@@ -2099,6 +2101,8 @@ int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
 int _mmcamcorder_video_prepare_record(MMHandleType handle)
 {
        int ret = MM_ERROR_NONE;
+       int size = 0;
+       char *temp_filename = NULL;
 
        _MMCamcorderVideoInfo *info = NULL;
        _MMCamcorderSubContext *sc = NULL;
@@ -2119,25 +2123,25 @@ int _mmcamcorder_video_prepare_record(MMHandleType handle)
        if (ret != MM_ERROR_NONE)
                goto _ERR_PREPARE_RECORD;
 
-       if (info->filename == NULL) {
-               char *temp_filename = NULL;
-               int size = 0;
-
-               mm_camcorder_get_attributes(handle, NULL,
-                       MMCAM_TARGET_FILENAME, &temp_filename, &size,
-                       NULL);
-               if (temp_filename)
-                       info->filename = g_strdup(temp_filename);
+       SAFE_G_FREE(info->filename);
 
+       mm_camcorder_get_attributes(handle, NULL,
+               MMCAM_TARGET_FILENAME, &temp_filename, &size,
+               NULL);
+       if (temp_filename) {
+               info->filename = g_strdup(temp_filename);
                if (!info->filename) {
                        _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
                        goto _ERR_PREPARE_RECORD;
                }
-       }
 
-       _mmcam_dbg_log("Record file name [%s]", info->filename);
+               _mmcam_dbg_log("Record file name [%s]", info->filename);
+               MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
+       } else {
+               _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
+               MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
+       }
 
-       MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
        MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
 
        /* Adjust display FPS */