[Release 0.10.61] TSAM-6195 : Fix crash when stop camera
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_videorec.c
index 6a61fac..47fcb39 100644 (file)
@@ -46,7 +46,7 @@
 |    LOCAL FUNCTION PROTOTYPES:                                                                |
 ---------------------------------------------------------------------------------------*/
 /* STATIC INTERNAL FUNCTION */
-static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data);
+static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data);
 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
@@ -62,18 +62,18 @@ static GstPadProbeReturn __mmcamcorder_eventprobe_monitor(GstPad *pad, GstPadPro
 /*---------------------------------------------------------------------------------------
 |    GLOBAL FUNCTION DEFINITIONS:                                                      |
 ---------------------------------------------------------------------------------------*/
-static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
+static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
 {
        mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
        _MMCamcorderSubContext *sc = NULL;
 
        GstBuffer *buffer = gst_sample_get_buffer(sample);
-       mmf_return_if_fail(buffer);
-       mmf_return_if_fail(gst_buffer_n_memory(buffer));
-       mmf_return_if_fail(hcamcorder);
+       mmf_return_val_if_fail(buffer, FALSE);
+       mmf_return_val_if_fail(gst_buffer_n_memory(buffer), FALSE);
+       mmf_return_val_if_fail(hcamcorder, FALSE);
 
        sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
-       mmf_return_if_fail(sc);
+       mmf_return_val_if_fail(sc, FALSE);
 
        /*
        _mmcam_dbg_log("ENTER - push_encoding_buffer %d, buffer %p, MALLOCDATA %p, size %d",
@@ -123,7 +123,7 @@ static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample
                buffer = NULL;
        }
 
-       return;
+       return TRUE;
 }
 
 
@@ -288,6 +288,9 @@ int _mmcamcorder_create_recorder_pipeline(MMHandleType handle)
        /* register pipeline message callback */
        hcamcorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder);
 
+       /* set sync handler */
+       gst_bus_set_sync_handler(bus, _mmcamcorder_encode_pipeline_bus_sync_callback, (gpointer)hcamcorder, NULL);
+
        gst_object_unref(bus);
        bus = NULL;
 
@@ -506,6 +509,7 @@ int _mmcamcorder_video_command(MMHandleType handle, int command)
                        char *dir_name = NULL;
                        guint64 free_space = 0;
                        int file_system_type = 0;
+                       int root_directory_length = 0;
 
                        /* Recording */
                        _mmcam_dbg_log("Record Start - dual stream %d", info->support_dual_stream);
@@ -525,6 +529,7 @@ int _mmcamcorder_video_command(MMHandleType handle, int command)
                                                          MMCAM_TARGET_TIME_LIMIT, &imax_time,
                                                          MMCAM_FILE_FORMAT, &(info->fileformat),
                                                          MMCAM_CAMERA_RECORDING_MOTION_RATE, &motion_rate,
+                                                         MMCAM_ROOT_DIRECTORY, &hcamcorder->root_directory, &root_directory_length,
                                                          NULL);
                        if (ret != MM_ERROR_NONE) {
                                _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
@@ -586,13 +591,13 @@ int _mmcamcorder_video_command(MMHandleType handle, int command)
                                return MM_ERROR_OUT_OF_STORAGE;
                        }
 
-                       pthread_mutex_lock(&(hcamcorder->task_thread_lock));
+                       g_mutex_lock(&hcamcorder->task_thread_lock);
                        if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
                            hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
                                /* Play record start sound */
-                               _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_FILEPATH_REC_START_SND, FALSE);
+                               _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_START, FALSE);
                        }
-                       pthread_mutex_unlock(&(hcamcorder->task_thread_lock));
+                       g_mutex_unlock(&hcamcorder->task_thread_lock);
 
                        _mmcam_dbg_warn("video size [%dx%d]", info->video_width, info->video_height);
 
@@ -637,6 +642,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);
 
@@ -715,17 +727,17 @@ int _mmcamcorder_video_command(MMHandleType handle, int command)
                        }
 
                        /* check pre-created encode pipeline */
-                       pthread_mutex_lock(&(hcamcorder->task_thread_lock));
+                       g_mutex_lock(&hcamcorder->task_thread_lock);
                        if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
                            hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
                                /* create encoding pipeline */
                                ret =_mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
                                if (ret != MM_ERROR_NONE) {
-                                       pthread_mutex_unlock(&(hcamcorder->task_thread_lock));
+                                       g_mutex_unlock(&hcamcorder->task_thread_lock);
                                        goto _ERR_CAMCORDER_VIDEO_COMMAND;
                                }
                        }
-                       pthread_mutex_unlock(&(hcamcorder->task_thread_lock));
+                       g_mutex_unlock(&hcamcorder->task_thread_lock);
 
                        /* check recording start sound */
                        _mmcamcorder_sound_solo_play_wait(handle);
@@ -925,8 +937,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;
                        }
@@ -1017,7 +1036,16 @@ int _mmcamcorder_video_command(MMHandleType handle, int command)
                                }
                        }
 
-                       usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
+                       if (hcamcorder->capture_in_recording) {
+                               gint64 end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND);
+                               if (_MMCAMCORDER_CMD_WAIT_UNTIL(handle, end_time)) {
+                                       _mmcam_dbg_warn("signal received");
+                               } else {
+                                       _mmcam_dbg_warn("timeout");
+                               }
+                       } else {
+                               usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
+                       }
                }
 
                /* block push buffer */
@@ -1109,15 +1137,11 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle)
 
        if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_ASM) {
                /* Play record stop sound */
-               _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_FILEPATH_REC_STOP_SND, FALSE);
+               _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
        } else {
                _mmcam_dbg_warn("Play stop sound through pulseaudio");
 
-#ifdef _MMCAMCORDER_UPLOAD_SAMPLE
-               _mmcamcorder_sound_init(handle, _MMCAMCORDER_FILEPATH_REC_STOP_SND);
-#else /* _MMCAMCORDER_UPLOAD_SAMPLE */
                _mmcamcorder_sound_init(handle);
-#endif /* _MMCAMCORDER_UPLOAD_SAMPLE */
 
                _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, TRUE);
 
@@ -1186,6 +1210,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);
@@ -1217,11 +1247,11 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle)
 
        /* Send recording report to application */
        msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
-       report = (MMCamRecordingReport *)malloc(sizeof(MMCamRecordingReport));
+       report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
        if (!report) {
                _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
        } else {
-               report->recording_filename = strdup(info->filename);
+               report->recording_filename = g_strdup(info->filename);
                msg.param.data= report;
                msg.param.code = 1;
                _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
@@ -1323,18 +1353,18 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPad
 
        /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
 
-       pthread_mutex_lock(&(videoinfo->size_check_lock));
+       g_mutex_lock(&videoinfo->size_check_lock);
 
        if (videoinfo->audio_frame_count == 0) {
                videoinfo->filesize += buffer_size;
                videoinfo->audio_frame_count++;
-               pthread_mutex_unlock(&(videoinfo->size_check_lock));
+               g_mutex_unlock(&videoinfo->size_check_lock);
                return GST_PAD_PROBE_OK;
        }
 
        if (sc->ferror_send || sc->isMaxsizePausing) {
                _mmcam_dbg_warn("Recording is paused, drop frames");
-               pthread_mutex_unlock(&(videoinfo->size_check_lock));
+               g_mutex_unlock(&videoinfo->size_check_lock);
                return GST_PAD_PROBE_DROP;
        }
 
@@ -1366,7 +1396,7 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPad
                        _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
                }
 
-               pthread_mutex_unlock(&(videoinfo->size_check_lock));
+               g_mutex_unlock(&videoinfo->size_check_lock);
 
                return FALSE;
        }
@@ -1374,7 +1404,7 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPad
        videoinfo->filesize += buffer_size;
        videoinfo->audio_frame_count++;
 
-       pthread_mutex_unlock(&(videoinfo->size_check_lock));
+       g_mutex_unlock(&videoinfo->size_check_lock);
 
        return GST_PAD_PROBE_OK;
 }
@@ -1419,9 +1449,9 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPa
        if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
                /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
                                info->video_frame_count); */
-               pthread_mutex_lock(&(videoinfo->size_check_lock));
+               g_mutex_lock(&videoinfo->size_check_lock);
                videoinfo->filesize += buffer_size;
-               pthread_mutex_unlock(&(videoinfo->size_check_lock));
+               g_mutex_unlock(&videoinfo->size_check_lock);
                return GST_PAD_PROBE_OK;
        }
 
@@ -1495,7 +1525,7 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPa
                break;
        }
 
-       pthread_mutex_lock(&(videoinfo->size_check_lock));
+       g_mutex_lock(&videoinfo->size_check_lock);
 
        /* check max size of recorded file */
        if (videoinfo->max_size > 0 &&
@@ -1518,7 +1548,7 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPa
                        _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
                }
 
-               pthread_mutex_unlock(&(videoinfo->size_check_lock));
+               g_mutex_unlock(&videoinfo->size_check_lock);
 
                return GST_PAD_PROBE_DROP;
        }
@@ -1529,7 +1559,7 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPa
        _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
        */
 
-       pthread_mutex_unlock(&(videoinfo->size_check_lock));
+       g_mutex_unlock(&videoinfo->size_check_lock);
 
        return GST_PAD_PROBE_OK;
 }
@@ -2050,7 +2080,7 @@ int _mmcamcorder_video_prepare_record(MMHandleType handle)
                                            MMCAM_TARGET_FILENAME, &temp_filename, &size,
                                            NULL);
                if (temp_filename) {
-                       info->filename = strdup(temp_filename);
+                       info->filename = g_strdup(temp_filename);
                }
 
                if (!info->filename) {
@@ -2061,7 +2091,7 @@ int _mmcamcorder_video_prepare_record(MMHandleType handle)
 
        _mmcam_dbg_log("Record file name [%s]", info->filename);
 
-       MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
+       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 */