*/
/*=======================================================================================
-| INCLUDE FILES |
+| INCLUDE FILES |
=======================================================================================*/
-#include <gst/interfaces/cameracontrol.h>
+#include <gst/allocators/gsttizenmemory.h>
+#include <gst/video/cameracontrol.h>
+#include <gst/app/gstappsrc.h>
#include "mm_camcorder_internal.h"
#include "mm_camcorder_videorec.h"
/*---------------------------------------------------------------------------------------
-| GLOBAL VARIABLE DEFINITIONS for internal |
+| LOCAL VARIABLE DEFINITIONS for internal |
---------------------------------------------------------------------------------------*/
-#define _MMCAMCORDER_LOCATION_INFO // for add gps information
-#define MAX_ERROR_MESSAGE_LEN 128
+#define _MMCAMCORDER_MINIMUM_FRAME 5
+#define _MMCAMCORDER_RETRIAL_COUNT 15
+#define _MMCAMCORDER_FRAME_WAIT_TIME 200000 /* us */
+#define _MMCAMCORDER_FRAME_PASS_MIN_FPS 30
+#define _MMCAMCORDER_MIN_TIME_TO_PASS_FRAME 30000000 /* ns */
+#define _MMCAMCORDER_VIDEO_MINIMUM_SPACE (_MMCAMCORDER_MINIMUM_SPACE << 1) /* byte */
+#define OFFSET_COMPOSITION_MATRIX 40L
+#define MAX_ERROR_MESSAGE_LEN 128
/*---------------------------------------------------------------------------------------
-| LOCAL VARIABLE DEFINITIONS for internal |
----------------------------------------------------------------------------------------*/
-#define _MMCAMCORDER_MINIMUM_FRAME 3
-#define _MMCAMCORDER_RETRIAL_COUNT 10
-#define _MMCAMCORDER_FRAME_WAIT_TIME 200000 /* ms */
-#define _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL 5
-#define _OFFSET_COMPOSITION_MATRIX 40L
-
-/*---------------------------------------------------------------------------------------
-| LOCAL FUNCTION PROTOTYPES: |
+| LOCAL FUNCTION PROTOTYPES: |
---------------------------------------------------------------------------------------*/
/* STATIC INTERNAL FUNCTION */
-static gboolean __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstBuffer *buffer, gpointer u_data);
-static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buffer, gpointer u_data);
-static gboolean __mmcamcorder_audioque_dataprobe(GstPad *pad, GstBuffer *buffer, gpointer u_data);
-static gboolean __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstBuffer *buffer, gpointer u_data);
-static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer *buffer, gpointer u_data);
-static gboolean __mmcamcorder_add_locationinfo(MMHandleType handle, int fileformat);
-static gboolean __mmcamcorder_add_locationinfo_mp4(MMHandleType handle);
-static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, gpointer u_data);
+static void __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_encoded(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
+static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
+static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
+static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
+static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat);
+static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle);
/*=======================================================================================
| FUNCTION DEFINITIONS |
/*---------------------------------------------------------------------------------------
| GLOBAL FUNCTION DEFINITIONS: |
---------------------------------------------------------------------------------------*/
-int _mmcamcorder_add_recorder_pipeline(MMHandleType handle)
+gboolean _mmcamcorder_video_push_buffer(void *handle, GstSample *sample)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderImageInfo *info_image = NULL;
+ _MMCamcorderVideoInfo *info_video = NULL;
+ _MMCamcorderGstElement *element = NULL;
+ GstClockTime current_ts = 0; /* nsec */
+ GstBuffer *buffer = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+ mmf_return_val_if_fail(MMF_CAMCORDER_SUBCONTEXT(hcamcorder), FALSE);
+
+ buffer = gst_sample_get_buffer(sample);
+
+ mmf_return_val_if_fail(buffer, FALSE);
+ mmf_return_val_if_fail(gst_buffer_n_memory(buffer), FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+
+ mmf_return_val_if_fail(sc->info_image, FALSE);
+ mmf_return_val_if_fail(sc->info_video, FALSE);
+ mmf_return_val_if_fail(sc->encode_element, FALSE);
+
+ info_image = sc->info_image;
+ info_video = sc->info_video;
+ element = sc->encode_element;
+
+ if (info_video->push_encoding_buffer == PUSH_ENCODING_BUFFER_RUN &&
+ element[_MMCAMCORDER_ENCSINK_SRC].gst) {
+ int ret = 0;
+ GstClock *clock = NULL;
+
+ MMCAM_LOG_VERBOSE("GST_BUFFER_FLAG_DELTA_UNIT is set : %d",
+ GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT));
+
+ current_ts = GST_BUFFER_PTS(buffer);
+
+ if (info_video->is_first_frame) {
+ /* check first I frame for H.264 stream */
+ if (_mmcamcorder_is_encoded_preview_pixel_format(info_image->preview_format)) {
+ if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
+ MMCAM_LOG_WARNING("NOT key frame.. skip this buffer");
+ return TRUE;
+ } else {
+ MMCAM_LOG_WARNING("first key frame");
+ }
+ }
+
+ /* set base timestamp */
+ if (element[_MMCAMCORDER_AUDIOSRC_SRC].gst) {
+ clock = GST_ELEMENT_CLOCK(element[_MMCAMCORDER_AUDIOSRC_SRC].gst);
+ if (clock) {
+ gst_object_ref(clock);
+ info_video->base_video_ts = current_ts - (gst_clock_get_time(clock) - \
+ GST_ELEMENT(element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time);
+ gst_object_unref(clock);
+ }
+ } else {
+ /* for image capture with encodebin and v4l2src */
+ if (sc->bencbin_capture && 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;
+ g_cond_signal(&hcamcorder->task_thread_cond);
+ g_mutex_unlock(&hcamcorder->task_thread_lock);
+ }
+ info_video->base_video_ts = current_ts;
+ }
+ } else {
+ if (_mmcamcorder_invoke_video_stream_cb(handle, sample, FALSE, -1) == FALSE) {
+ /* increase base video timestamp by frame duration,
+ it will remove delay of dropped buffer when play recorded file. */
+ info_video->base_video_ts += current_ts - info_video->last_video_ts;
+ MMCAM_LOG_DEBUG("do not push buffer to encode by app's return value");
+ goto _VIDEO_PUSH_BUFFER_DONE;
+ }
+ }
+
+ GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer) = current_ts - info_video->base_video_ts;
+
+ MMCAM_LOG_DEBUG("buffer %p, timestamp %"GST_TIME_FORMAT,
+ buffer, GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));
+
+ if (info_video->record_dual_stream) {
+ /* It will NOT INCREASE reference count of buffer */
+ ret = gst_app_src_push_buffer((GstAppSrc *)element[_MMCAMCORDER_ENCSINK_SRC].gst, buffer);
+ } else {
+ /* It will INCREASE reference count of buffer */
+ g_signal_emit_by_name(element[_MMCAMCORDER_ENCSINK_SRC].gst, "push-buffer", buffer, &ret);
+ }
+
+ MMCAM_LOG_VERBOSE("push buffer result : 0x%x", ret);
+
+_VIDEO_PUSH_BUFFER_DONE:
+ info_video->last_video_ts = current_ts;
+
+ if (info_video->is_first_frame) {
+ info_video->is_first_frame = FALSE;
+
+ /* drop buffer if it's from tizen allocator */
+ if (gst_is_tizen_memory(gst_buffer_peek_memory(buffer, 0))) {
+ MMCAM_LOG_WARNING("drop first buffer from tizen allocator to avoid copy in basesrc");
+ return FALSE;
+ }
+ }
+ }
+
+ /* skip display if too fast FPS */
+ if (info_video->record_dual_stream == FALSE &&
+ info_video->fps > _MMCAMCORDER_FRAME_PASS_MIN_FPS) {
+ if (info_video->prev_preview_ts != 0) {
+ if (GST_BUFFER_PTS(buffer) - info_video->prev_preview_ts < _MMCAMCORDER_MIN_TIME_TO_PASS_FRAME) {
+ MMCAM_LOG_VERBOSE("it's too fast. drop frame...");
+ return FALSE;
+ }
+ }
+
+ MMCAM_LOG_VERBOSE("display buffer [%p]", buffer);
+
+ info_video->prev_preview_ts = GST_BUFFER_PTS(buffer);
+ }
+
+ return TRUE;
+}
+
+
+static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
+{
+ mmf_return_if_fail(sample);
+
+ /* no need to check return value here */
+ _mmcamcorder_video_push_buffer(u_data, sample);
+
+ gst_sample_unref(sample);
+}
+
+
+int _mmcamcorder_create_recorder_pipeline(MMHandleType handle)
{
+ int i = 0;
int err = MM_ERROR_NONE;
- int audio_disable = FALSE;
- char* gst_element_rsink_name = NULL;
+ const char* gst_element_rsink_name = NULL;
+ GstBus *bus = NULL;
GstPad *srcpad = NULL;
GstPad *sinkpad = NULL;
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);
-
- _mmcam_dbg_log("");
- err = _mmcamcorder_check_videocodec_fileformat_compatibility( handle );
- if( err != MM_ERROR_NONE )
- {
+ MMCAM_LOG_WARNING("start");
+
+ err = _mmcamcorder_check_videocodec_fileformat_compatibility(handle);
+ if (err != MM_ERROR_NONE)
return err;
- }
- /* Create gstreamer element */
- /* Check main pipeline */
- if (!sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
- err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
- goto pipeline_creation_error;
+ /* Main pipeline */
+ if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
+ MMCAM_LOG_INFO("pipeline is exist so need to remove pipeline _MMCAMCORDER_ENCODE_MAIN_PIPE = %p",
+ sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
+ _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
}
+ _MMCAMCORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
+
/* get audio disable */
mm_camcorder_get_attributes(handle, NULL,
- MMCAM_AUDIO_DISABLE, &audio_disable,
- NULL);
+ MMCAM_AUDIO_DISABLE, &sc->audio_disable,
+ NULL);
- if (sc->is_modified_rate || audio_disable) {
+ MMCAM_LOG_INFO("MMCAM_AUDIO_DISABLE %d, is_modified_rate %d, ved_cb %p",
+ sc->audio_disable, sc->is_modified_rate, hcamcorder->vedecision_cb);
+
+ if (sc->is_modified_rate || hcamcorder->vedecision_cb)
sc->audio_disable = TRUE;
- } else {
- sc->audio_disable = FALSE;
- }
- _mmcam_dbg_log("AUDIO DISABLE : %d (is_modified_rate %d, audio_disable %d)",
- sc->audio_disable, sc->is_modified_rate, audio_disable);
if (sc->audio_disable == FALSE) {
- /* Sub pipeline */
- __ta__(" __mmcamcorder_create_audiosrc_bin",
+ /* create audiosrc bin */
err = _mmcamcorder_create_audiosrc_bin((MMHandleType)hcamcorder);
- );
- if (err != MM_ERROR_NONE) {
+ if (err != MM_ERROR_NONE)
return err;
- }
-
- gst_bin_add(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
- sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
}
- __ta__(" _mmcamcorder_create_encodesink_bin",
err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder, MM_CAMCORDER_ENCBIN_PROFILE_VIDEO);
- );
- if (err != MM_ERROR_NONE) {
+ if (err != MM_ERROR_NONE)
return err;
+
+ if (sc->audio_disable == FALSE) {
+ gst_bin_add(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
+ sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
}
- gst_bin_add(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
- sc->element[_MMCAMCORDER_ENCSINK_BIN].gst);
+ /* add elements and encodesink bin to encode main pipeline */
+ if (sc->info_video->use_videoscale) {
+ 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_VSCALE].gst,
+ sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_FILT].gst,
+ sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
+ NULL);
+ } else {
+ 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_BIN].gst,
+ NULL);
+ }
- /* Link each element */
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, "src1");
- sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
+ /* 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");
+ _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");
+ if (sc->info_video->use_videoscale) {
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE].gst, "sink");
+ _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
+
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE].gst, "src");
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_FILT].gst, "sink");
+ _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
+
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VSCALE_FILT].gst, "src");
+ }
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
_MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
if (sc->audio_disable == FALSE) {
- srcpad = gst_element_get_static_pad (sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
- sinkpad = gst_element_get_static_pad (sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
_MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
}
- _mmcamcorder_conf_get_element(hcamcorder->conf_main,
- CONFIGURE_CATEGORY_MAIN_RECORD,
- "RecordsinkElement",
- &RecordsinkElement);
+ _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);
+ if (!gst_element_rsink_name) {
+ MMCAM_LOG_ERROR("failed to get recordsink name");
+ err = MM_ERROR_CAMCORDER_INTERNAL;
+ goto pipeline_creation_error;
+ }
+
/* set data probe function */
/* register message cb */
- /* set data probe function for audio */
-
+ /* set data probe functions */
if (sc->audio_disable == FALSE) {
- sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "sink");
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "sink");
MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
- __mmcamcorder_audioque_dataprobe, hcamcorder);
+ __mmcamcorder_audioque_dataprobe, hcamcorder);
gst_object_unref(sinkpad);
sinkpad = NULL;
-
+
/* for voice mute */
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
- __mmcamcorder_audio_dataprobe_audio_mute, hcamcorder);
+ __mmcamcorder_audio_dataprobe_audio_mute, hcamcorder);
gst_object_unref(srcpad);
srcpad = NULL;
- if (sc->element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "src");
+ if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "src");
MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
- __mmcamcorder_eventprobe_monitor, hcamcorder);
+ __mmcamcorder_eventprobe_monitor, hcamcorder);
gst_object_unref(srcpad);
srcpad = NULL;
}
}
- if (sc->element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "src");
+ if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "src");
MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
- __mmcamcorder_eventprobe_monitor, hcamcorder);
+ __mmcamcorder_eventprobe_monitor, hcamcorder);
gst_object_unref(srcpad);
srcpad = NULL;
}
if (sc->audio_disable) {
- sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "sink");
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "sink");
MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
- __mmcamcorder_video_dataprobe_audio_disable, hcamcorder);
+ __mmcamcorder_video_dataprobe_audio_disable, hcamcorder);
gst_object_unref(sinkpad);
sinkpad = NULL;
}
if (!strcmp(gst_element_rsink_name, "filesink")) {
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
- __mmcamcorder_video_dataprobe_record, hcamcorder);
+ __mmcamcorder_video_dataprobe_encoded, hcamcorder);
gst_object_unref(srcpad);
srcpad = NULL;
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
- __mmcamcorder_audio_dataprobe_check, hcamcorder);
+ __mmcamcorder_audio_dataprobe_check, hcamcorder);
gst_object_unref(srcpad);
srcpad = NULL;
}
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "sink");
+ MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_muxed_dataprobe, hcamcorder);
+ MMCAMCORDER_ADD_EVENT_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_eventprobe_monitor, hcamcorder);
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+
+ bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
+
+ /* set sync handler */
+ gst_bus_set_sync_handler(bus, _mmcamcorder_encode_pipeline_bus_sync_callback, (gpointer)hcamcorder, NULL);
+
+ gst_object_unref(bus);
+ bus = NULL;
+
return MM_ERROR_NONE;
pipeline_creation_error:
+ for (i = _MMCAMCORDER_AUDIOSRC_BIN ; i <= _MMCAMCORDER_ENCSINK_SINK ; i++)
+ _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, i);
+
+ _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE);
return err;
}
int _mmcamcorder_remove_audio_pipeline(MMHandleType handle)
{
- int ret = MM_ERROR_NONE;
GstPad *srcpad = NULL;
GstPad *sinkpad = NULL;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
- _mmcam_dbg_log("");
-
- if (sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst != NULL) {
- __ta__( " AudiosrcBin Set NULL",
- ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst, GST_STATE_NULL);
- );
- if (ret != MM_ERROR_NONE) {
- _mmcam_dbg_err("Faile to change audio source state[%d]", ret);
- return ret;
- }
+ MMCAM_LOG_INFO("");
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
- sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
+ if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst != NULL) {
+ srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
+ sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
_MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
- gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
- sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
+ /* release audiosrc bin */
+ gst_bin_remove(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
+ sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
/*
To avoid conflicting between old elements and newly created elements,
It's because the pipeline of audio recording destroys at the same time,
and '_mmcamcorder_element_release_noti' will perfom removing handle.
*/
- _mmcamcorder_remove_element_handle(handle, _MMCAMCORDER_AUDIOSRC_BIN, _MMCAMCORDER_AUDIOSRC_NS);
+ _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element, _MMCAMCORDER_AUDIOSRC_BIN, _MMCAMCORDER_AUDIOSRC_VOL);
- _mmcam_dbg_log("Audio pipeline removed");
+ MMCAM_LOG_INFO("Audio pipeline removed");
}
return MM_ERROR_NONE;
}
-int _mmcamcorder_remove_encoder_pipeline(MMHandleType handle)
+int _mmcamcorder_remove_encode_pipeline(MMHandleType handle)
{
- int ret = MM_ERROR_NONE;
- GstPad *srcpad = NULL;
- GstPad *sinkpad = NULL;
GstPad *reqpad = NULL;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
_MMCamcorderSubContext *sc = NULL;
-
+#ifdef _MMCAMCORDER_MM_RM_SUPPORT
+ int ret = MM_ERROR_NONE;
+#endif /* _MMCAMCORDER_MM_RM_SUPPORT */
+
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);
- _mmcam_dbg_log("");
-
- if (sc->element[_MMCAMCORDER_ENCSINK_BIN].gst != NULL) {
- __ta__( " EncodeBin Set NULL",
- ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, GST_STATE_NULL);
- );
- if (ret != MM_ERROR_NONE) {
- _mmcam_dbg_err("Faile to change encode bin state[%d]", ret);
- return ret;
- }
-
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, "src1");
- sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
- _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
+ MMCAM_LOG_INFO("");
+ if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst != NULL) {
/* release request pad */
- reqpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
+ reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
if (reqpad) {
- gst_element_release_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
+ gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
gst_object_unref(reqpad);
reqpad = NULL;
}
- reqpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
+ reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
if (reqpad) {
- gst_element_release_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
+ gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
gst_object_unref(reqpad);
reqpad = NULL;
}
- gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
- sc->element[_MMCAMCORDER_ENCSINK_BIN].gst);
+ /* release encode main pipeline */
+ gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
/*
To avoid conflicting between old elements and newly created elements,
It's because the pipeline of audio recording destroys at the same time,
and '_mmcamcorder_element_release_noti' will perfom removing handle.
*/
- _mmcamcorder_remove_element_handle(handle, _MMCAMCORDER_AUDIOSRC_QUE, _MMCAMCORDER_AUDIOSRC_ENC); /* Encode bin has audio encoder too. */
- _mmcamcorder_remove_element_handle(handle, _MMCAMCORDER_ENCSINK_BIN, _MMCAMCORDER_ENCSINK_SINK);
+ /* _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element,
+ _MMCAMCORDER_ENCODE_MAIN_PIPE, _MMCAMCORDER_ENCSINK_SINK); */
+
+ MMCAM_LOG_WARNING("Encoder pipeline removed");
+
+#ifdef _MMCAMCORDER_MM_RM_SUPPORT
+ _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
+
+ MMCAM_LOG_WARNING("lock resource - cb calling %d", hcamcorder->is_release_cb_calling);
- _mmcam_dbg_log("Encoder pipeline removed");
+ if (hcamcorder->is_release_cb_calling == FALSE) {
+ /* release resource */
+ ret = mm_resource_manager_mark_for_release(hcamcorder->resource_manager,
+ hcamcorder->video_encoder_resource);
+ if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
+ hcamcorder->video_encoder_resource = NULL;
+
+ MMCAM_LOG_WARNING("mark resource for release 0x%x", ret);
+
+ ret = mm_resource_manager_commit(hcamcorder->resource_manager);
+
+ MMCAM_LOG_WARNING("commit resource release 0x%x", ret);
+ }
+
+ _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
+
+ MMCAM_LOG_WARNING("unlock resource");
+#endif /* _MMCAMCORDER_MM_RM_SUPPORT */
}
return MM_ERROR_NONE;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
_MMCamcorderSubContext *sc = NULL;
+ GstBus *bus = 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);
- _mmcam_dbg_log("");
+ MMCAM_LOG_INFO("start");
- if (!sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
- _mmcam_dbg_warn("pipeline is not existed.");
+ if (!sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
+ MMCAM_LOG_WARNING("pipeline is not existed.");
return MM_ERROR_NONE;
}
_mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_VIDEOREC);
+ ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
+ if (ret != MM_ERROR_NONE) {
+ MMCAM_LOG_ERROR("Failed to change encode main pipeline [0x%x]", ret);
+ return ret;
+ }
+
+ bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
+
/* remove audio pipeline first */
ret = _mmcamcorder_remove_audio_pipeline(handle);
if (ret != MM_ERROR_NONE) {
- _mmcam_dbg_err("Fail to remove audio pipeline");
+ MMCAM_LOG_ERROR("Fail to remove audio pipeline");
return ret;
}
- ret = _mmcamcorder_remove_encoder_pipeline(handle);
+ ret = _mmcamcorder_remove_encode_pipeline(handle);
if (ret != MM_ERROR_NONE) {
- _mmcam_dbg_err("Fail to remove encoder pipeline");
+ MMCAM_LOG_ERROR("Fail to remove encoder pipeline");
return ret;
}
- return ret;
-}
-
-
-void _mmcamcorder_destroy_video_pipeline(MMHandleType handle)
-{
- mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
- _MMCamcorderSubContext *sc = NULL;
- GstPad *reqpad1 = NULL;
- GstPad *reqpad2 = NULL;
-
- mmf_return_if_fail(hcamcorder);
- sc = MMF_CAMCORDER_SUBCONTEXT(handle);
-
- mmf_return_if_fail(sc);
- mmf_return_if_fail(sc->element);
-
- _mmcam_dbg_log("");
-
- if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
- _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_NULL);
-
- _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_CATEGORY_ALL);
+ /* Remove remained message */
+ if (bus) {
+ GstMessage *gst_msg = NULL;
+ while ((gst_msg = gst_bus_pop(bus)) != NULL) {
+ _mmcamcorder_pipeline_cb_message(bus, gst_msg, (gpointer)hcamcorder);
+ gst_message_unref(gst_msg);
+ gst_msg = NULL;
+ }
+ gst_object_unref(bus);
+ bus = NULL;
+ }
- reqpad1 = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, "src0");
- reqpad2 = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, "src1");
- gst_element_release_request_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, reqpad1);
- gst_element_release_request_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, reqpad2);
- gst_object_unref(reqpad1);
- gst_object_unref(reqpad2);
+ MMCAM_LOG_INFO("done");
- /* object disposing problem happen. */
- _mmcam_dbg_log("Reference count of pipeline(%d)", GST_OBJECT_REFCOUNT_VALUE(sc->element[_MMCAMCORDER_MAIN_PIPE].gst));
- gst_object_unref(sc->element[_MMCAMCORDER_MAIN_PIPE].gst);
- }
+ return ret;
}
{
int size = 0;
int fileformat = 0;
+ int count = 0;
+ int gop_interval = 0;
int ret = MM_ERROR_NONE;
double motion_rate = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
- char *temp_filename = NULL;
char *err_name = NULL;
+ char *target_filename = NULL;
+ GstCameraControl *CameraControl = NULL;
gint fps = 0;
GstElement *pipeline = NULL;
- GstPad *pad = NULL;
_MMCamcorderVideoInfo *info = NULL;
_MMCamcorderSubContext *sc = NULL;
info = sc->info_video;
- _mmcam_dbg_log("Command(%d)", command);
+ MMCAM_LOG_INFO("Command(%d)", command);
pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
case _MMCamcorder_CMD_RECORD:
{
if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED) {
+ /**
+ * start recording
+ */
+ gboolean storage_validity = FALSE;
guint imax_size = 0;
guint imax_time = 0;
-
- /* Play record start sound */
- _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_FILEPATH_REC_START_SND, TRUE);
+ int root_directory_length = 0;
/* Recording */
- _mmcam_dbg_log("Record Start");
-
- /* set hybrid mode when ITLV format */
- if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ITLV_JPEG_UYVY) {
- _mmcam_dbg_log("flush cache TRUE");
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "flush-cache", TRUE);
+ MMCAM_LOG_INFO("Record Start - dual stream %d", info->support_dual_stream);
+
+#ifdef _MMCAMCORDER_MM_RM_SUPPORT
+ _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
+
+ /* prepare resource manager for H/W encoder */
+ if (hcamcorder->video_encoder_resource == NULL) {
+ ret = mm_resource_manager_mark_for_acquire(hcamcorder->resource_manager,
+ MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_ENCODER,
+ MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
+ &hcamcorder->video_encoder_resource);
+ if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ MMCAM_LOG_ERROR("could not prepare for encoder resource");
+ ret = MM_ERROR_RESOURCE_INTERNAL;
+ _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+ } else {
+ MMCAM_LOG_INFO("encoder already acquired");
}
- ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
- if (ret != MM_ERROR_NONE) {
+ /* acquire resources */
+ ret = mm_resource_manager_commit(hcamcorder->resource_manager);
+ if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ MMCAM_LOG_ERROR("could not acquire resources");
+ ret = MM_ERROR_RESOURCE_INTERNAL;
+ _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
- _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
- CONFIGURE_CATEGORY_MAIN_RECORD,
- "DropVideoFrame",
- &(sc->drop_vframe));
+ _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
+#endif /* _MMCAMCORDER_MM_RM_SUPPORT */
- _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
- CONFIGURE_CATEGORY_MAIN_RECORD,
- "PassFirstVideoFrame",
- &(sc->pass_first_vframe));
-
- _mmcam_dbg_log("Drop video frame count[%d], Pass fisrt video frame count[%d]",
- sc->drop_vframe, sc->pass_first_vframe);
+ /* init record_dual_stream */
+ info->record_dual_stream = FALSE;
ret = mm_camcorder_get_attributes(handle, &err_name,
- MMCAM_CAMERA_FPS, &fps,
- MMCAM_CAMERA_RECORDING_MOTION_RATE, &motion_rate,
- MMCAM_FILE_FORMAT, &fileformat,
- MMCAM_TARGET_FILENAME, &temp_filename, &size,
- MMCAM_TARGET_MAX_SIZE, &imax_size,
- MMCAM_TARGET_TIME_LIMIT, &imax_time,
- MMCAM_FILE_FORMAT, &(info->fileformat),
- NULL);
+ MMCAM_CAMERA_FPS, &fps,
+ MMCAM_CAMERA_WIDTH, &(info->preview_width),
+ MMCAM_CAMERA_HEIGHT, &(info->preview_height),
+ MMCAM_VIDEO_WIDTH, &(info->video_width),
+ MMCAM_VIDEO_HEIGHT, &(info->video_height),
+ MMCAM_FILE_FORMAT, &fileformat,
+ MMCAM_TARGET_FILENAME, &target_filename, &size,
+ MMCAM_TARGET_MAX_SIZE, &imax_size,
+ 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);
- SAFE_FREE (err_name);
+ MMCAM_LOG_WARNING("Get attrs fail. (%s:%x)", err_name, ret);
+ SAFE_FREE(err_name);
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ if (!target_filename && !hcamcorder->mstream_cb) {
+ MMCAM_LOG_ERROR("filename is not set and muxed stream cb is NULL");
+ ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
/* set max size */
- if (imax_size <= 0) {
+ if (imax_size <= 0)
info->max_size = 0; /* do not check */
- } else {
+ else
info->max_size = ((guint64)imax_size) << 10; /* to byte */
- }
/* set max time */
- if (imax_time <= 0) {
+ if (imax_time <= 0)
info->max_time = 0; /* do not check */
- } else {
- info->max_time = ((guint64)imax_time) * 1000; /* to millisecond */
+ else
+ info->max_time = (guint64)((double)imax_time * (double)1000 * motion_rate); /* to millisecond */
+
+ ret = _mmcamcorder_get_storage_validity(hcamcorder, target_filename,
+ _MMCAMCORDER_VIDEO_MINIMUM_SPACE, &storage_validity);
+ if (ret != MM_ERROR_NONE) {
+ MMCAM_LOG_ERROR("storage validation failed[0x%x]:%d", ret, storage_validity);
+ return ret;
}
- if (sc->is_modified_rate) {
- info->record_timestamp_ratio = (_MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE/motion_rate);
- _mmcam_dbg_log("high speed recording fps:%d, slow_rate:%f, timestamp_ratio:%f",
- fps, motion_rate, info->record_timestamp_ratio);
+ _mmcamcorder_adjust_recording_max_size(target_filename, &info->max_size);
+
+ 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_SAMPLE_SOUND_NAME_REC_START, FALSE);
+ }
+ g_mutex_unlock(&hcamcorder->task_thread_lock);
+
+ MMCAM_LOG_WARNING("video size [%dx%d]", info->video_width, info->video_height);
+
+ if (info->video_width == 0 || info->video_height == 0) {
+ MMCAM_LOG_WARNING("video size is invalid [%dx%d] use preview size [%dx%d]",
+ info->video_width, info->video_height, info->preview_width, info->preview_height);
+ info->video_width = info->preview_width;
+ info->video_height = info->preview_height;
+ }
+
+ if (info->support_dual_stream) {
+ MMCAM_LOG_WARNING("DUAL STREAM MODE");
+
+ info->record_dual_stream = TRUE;
+
+ /* No need to restart preview */
+ info->restart_preview = FALSE;
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height);
+ } else if (_mmcamcorder_is_encoded_preview_pixel_format(sc->info_image->preview_format) &&
+ info->preview_width == info->video_width &&
+ info->preview_height == info->video_height) {
+ MMCAM_LOG_INFO("Encoded[%d] preview mode and same resolution", sc->info_image->preview_format);
+ /* No need to restart preview */
+ info->restart_preview = FALSE;
+ } else if (info->use_videoscale &&
+ info->preview_width >= info->video_width &&
+ info->preview_height >= info->video_height) {
+ info->restart_preview = FALSE;
} else {
- info->record_timestamp_ratio = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
- _mmcam_dbg_log("normal recording");
+ info->restart_preview = TRUE;
+ /* reset use_videoscale */
+ info->use_videoscale = FALSE;
}
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hold-af-after-capturing", TRUE);
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "req-negotiation", TRUE);
+ /* set recording hint */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", TRUE);
- ret =_mmcamcorder_add_recorder_pipeline((MMHandleType)hcamcorder);
- if (ret != MM_ERROR_NONE) {
- goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ if (info->restart_preview) {
+ /* stop preview and set new size */
+ MMCAM_LOG_INFO("restart preview");
+
+ 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);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
+
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+
+ /* check decoder recreation */
+ if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
+ MMCAM_LOG_ERROR("_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);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
+
+ if (ret != MM_ERROR_NONE)
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+
+ if (!_mmcamcorder_set_camera_resolution(handle, info->video_width, info->video_height)) {
+ ret = MM_ERROR_CAMCORDER_INTERNAL;
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ /* Start preview again with new setting */
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ if (ret != MM_ERROR_NONE)
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+
+ if (motion_rate < 1.0) {
+ MMCAM_LOG_WARNING("wait for stabilization of frame");
+ usleep(300000);
+ }
+ } else {
+ MMCAM_LOG_INFO("no need to restart preview");
}
- info->filename = strdup(temp_filename);
- if (!info->filename) {
- _mmcam_dbg_err("strdup was failed");
- goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "DropVideoFrame",
+ &(sc->drop_vframe));
+
+ _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "PassFirstVideoFrame",
+ &(sc->pass_first_vframe));
+
+ MMCAM_LOG_INFO("Drop video frame count[%d], Pass fisrt video frame count[%d]",
+ sc->drop_vframe, sc->pass_first_vframe);
+
+ info->record_drop_count = (guint)motion_rate;
+ info->record_motion_rate = motion_rate;
+ if (sc->is_modified_rate)
+ info->record_timestamp_ratio = (_MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE/motion_rate);
+ else
+ info->record_timestamp_ratio = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
+
+ MMCAM_LOG_WARNING("recording fps %d, motion rate %f, timestamp_ratio %f",
+ fps, info->record_motion_rate, info->record_timestamp_ratio);
+
+ /* set push buffer flag */
+ info->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT;
+ info->base_video_ts = 0;
+
+ /* connect video stream cb signal if it supports dual stream. */
+ if (info->record_dual_stream) {
+ if (_mmcamcorder_connect_video_stream_cb_signal((MMHandleType)hcamcorder) != MM_ERROR_NONE)
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
- _mmcam_dbg_log("Record start : set file name using attribute - %s ",info->filename);
+ /* start video stream */
+ if (info->record_dual_stream) {
+ CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if (CameraControl) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
- MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
+ MMCAM_LOG_INFO("GST_CAMERA_CONTROL_RECORD_COMMAND_START");
+ gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_START);
- /* Adjust display FPS */
- sc->display_interval = 0;
- sc->previous_slot_time = 0;
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
+ } else {
+ MMCAM_LOG_ERROR("could not get camera control");
+ }
+ }
- /* gst_element_set_base_time(GST_ELEMENT(pipeline), (GstClockTime)0);
- if you want to use audio clock, enable this block
- for change recorder_pipeline state to paused. */
- __ta__(" _MMCamcorder_CMD_RECORD:GST_STATE_PAUSED2",
- ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PAUSED);
- );
- if (ret != MM_ERROR_NONE) {
- /* Remove recorder pipeline and recording file which size maybe zero */
- __ta__(" record fail:remove_recorder_pipeline",
- _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
- );
- if (info->filename) {
- _mmcam_dbg_log("file delete(%s)", info->filename);
- unlink(info->filename);
- g_free(info->filename);
- info->filename = NULL;
+ /* check pre-created encode pipeline */
+ 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) {
+ g_mutex_unlock(&hcamcorder->task_thread_lock);
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
- goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
+ g_mutex_unlock(&hcamcorder->task_thread_lock);
+
+ /* check recording start sound */
+ _mmcamcorder_sound_solo_play_wait(handle);
/**< To fix video recording hanging
1. use gst_element_set_start_time() instead of gst_pipeline_set_new_stream_time()
basetime wouldn't change if you set (GstClockTime)0.
3. Move set start time position below PAUSED of pipeline.
*/
- gst_element_set_start_time(GST_ELEMENT(pipeline), (GstClockTime)1);
+ /*
+ gst_element_set_start_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), (GstClockTime)1);
+ gst_element_set_start_time(GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), (GstClockTime)1);
+ */
+
info->video_frame_count = 0;
+ info->is_first_frame = TRUE;
info->audio_frame_count = 0;
info->filesize = 0;
sc->ferror_send = FALSE;
sc->ferror_count = 0;
- sc->error_occurs = FALSE;
+ hcamcorder->error_occurs = FALSE;
sc->bget_eos = FALSE;
+ sc->muxed_stream_offset = 0;
- __ta__(" _MMCamcorder_CMD_RECORD:GST_STATE_PLAYING2",
- ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
- );
+ ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
if (ret != MM_ERROR_NONE) {
+ /* stop video stream */
+ if (info->record_dual_stream) {
+ CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if (CameraControl) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
+
+ MMCAM_LOG_INFO("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
+ gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
+ } else {
+ MMCAM_LOG_ERROR("failed to get camera control");
+ }
+ }
+
/* Remove recorder pipeline and recording file which size maybe zero */
- __ta__(" record fail:remove_recorder_pipeline",
_mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
- );
if (info->filename) {
- _mmcam_dbg_log("file delete(%s)", info->filename);
+ MMCAM_LOG_INFO("file delete(%s)", info->filename);
unlink(info->filename);
- g_free(info->filename);
- info->filename = NULL;
}
goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
+
+ /*set the GOP so that video record will get a new key frame*/
+ if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
+ if (mm_camcorder_get_attributes(handle, NULL,
+ MMCAM_ENCODED_PREVIEW_GOP_INTERVAL, &gop_interval, NULL) == MM_ERROR_NONE)
+ _mmcamcorder_set_encoded_preview_gop_interval(handle, gop_interval);
+ else
+ MMCAM_LOG_ERROR("get gop interval failed");
+ }
} else {
/* Resume case */
- int video_enc = 0;
-
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
-
- mm_camcorder_get_attributes(handle, NULL, MMCAM_VIDEO_ENCODER, &video_enc, NULL);
- if (video_enc == MM_VIDEO_CODEC_MPEG4) {
- MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "force-intra", TRUE);
+ if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
+ if (mm_camcorder_get_attributes(handle, NULL,
+ MMCAM_ENCODED_PREVIEW_GOP_INTERVAL, &gop_interval, NULL) == MM_ERROR_NONE)
+ _mmcamcorder_set_encoded_preview_gop_interval(handle, gop_interval);
+ else
+ MMCAM_LOG_ERROR("get gop interval failed");
}
- _mmcam_dbg_log("Object property settings done");
+ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
+
+ MMCAM_LOG_INFO("Object property settings done");
}
}
break;
case _MMCamcorder_CMD_PAUSE:
{
- int count = 0;
-
- if (info->b_commiting) {
- _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
+ if (info->b_committing) {
+ MMCAM_LOG_WARNING("now on committing previous file!!(command : %d)", command);
return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
}
if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
break;
} else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
- _mmcam_dbg_err("Pause fail, frame count %" G_GUINT64_FORMAT "",
- info->video_frame_count);
+ MMCAM_LOG_ERROR("Pause fail, frame count %"G_GUINT64_FORMAT, info->video_frame_count);
return MM_ERROR_CAMCORDER_INVALID_CONDITION;
} else {
- _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %" G_GUINT64_FORMAT "",
- count, info->video_frame_count);
+ MMCAM_LOG_WARNING("Waiting for enough video frame, retrial[%d], frame %"G_GUINT64_FORMAT, count, info->video_frame_count);
}
usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
break;
} else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
- _mmcam_dbg_err("Pause fail, frame count VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]",
- info->video_frame_count, info->audio_frame_count);
+ MMCAM_LOG_ERROR("Pause fail, frame count VIDEO[%"G_GUINT64_FORMAT"], AUDIO [%"G_GUINT64_FORMAT"]",
+ info->video_frame_count, info->audio_frame_count);
return MM_ERROR_CAMCORDER_INVALID_CONDITION;
} else {
- _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]",
- count, info->video_frame_count, info->audio_frame_count);
+ MMCAM_LOG_WARNING("Waiting for enough frames, retrial [%d], VIDEO[%"G_GUINT64_FORMAT"], AUDIO [%"G_GUINT64_FORMAT"]",
+ count, info->video_frame_count, info->audio_frame_count);
}
usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
}
}
- /* tee block */
- MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
+ /* block encodebin */
+ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
break;
}
case _MMCamcorder_CMD_CANCEL:
{
- if (info->b_commiting) {
- _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
+ if (info->b_committing) {
+ MMCAM_LOG_WARNING("now on committing previous file!!(command : %d)", command);
return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
}
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hold-af-after-capturing", FALSE);
+ for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
+ /* capturing */
+ if (hcamcorder->capture_in_recording == FALSE) {
+ break;
+ } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
+ MMCAM_LOG_ERROR("Failed to Wait capture data");
+ hcamcorder->capture_in_recording = FALSE;
+ break;
+ } else {
+ MMCAM_LOG_WARNING("Waiting for capture data - retrial [%d]", count);
+ }
- __ta__(" _MMCamcorder_CMD_CANCEL:GST_STATE_READY",
- ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
- );
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
- if (ret != MM_ERROR_NONE) {
+ usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
+ }
+
+ /* block push buffer */
+ info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
+
+ ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
+ if (ret != MM_ERROR_NONE)
goto _ERR_CAMCORDER_VIDEO_COMMAND;
+
+ /* set recording hint */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
+
+ /* stop video stream */
+ if (info->record_dual_stream) {
+ CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if (CameraControl) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
+
+ MMCAM_LOG_INFO("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
+ gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
+ } else {
+ MMCAM_LOG_ERROR("failed to get camera control");
+ }
}
- __ta__(" __mmcamcorder_remove_recorder_pipeline",
- _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
- );
+ if (info->restart_preview) {
+ /* restart preview */
+ 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);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
+
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+
+ /* check decoder recreation */
+ if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
+ MMCAM_LOG_ERROR("_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);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
+
+ if (ret != MM_ERROR_NONE)
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+
+ /* reset restart_preview for inset window layout */
+ info->restart_preview = FALSE;
+
+ if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
+ ret = MM_ERROR_CAMCORDER_INTERNAL;
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ if (ret != MM_ERROR_NONE)
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
/* remove target file */
if (info->filename) {
- _mmcam_dbg_log("file delete(%s)", info->filename);
+ MMCAM_LOG_INFO("file delete(%s)", info->filename);
unlink(info->filename);
- g_free(info->filename);
- info->filename = NULL;
}
sc->isMaxsizePausing = FALSE;
sc->previous_slot_time = 0;
info->video_frame_count = 0;
info->audio_frame_count = 0;
- info->filesize =0;
-
- /* set flush cache as FALSE */
- if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ITLV_JPEG_UYVY) {
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "flush-cache", FALSE);
- }
-
- __ta__(" _MMCamcorder_CMD_CANCEL:GST_STATE_PLAYING",
- ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
- );
- if (ret != MM_ERROR_NONE) {
- goto _ERR_CAMCORDER_VIDEO_COMMAND;
- }
+ info->filesize = 0;
+ hcamcorder->capture_in_recording = FALSE;
break;
}
case _MMCamcorder_CMD_COMMIT:
{
- int count = 0;
+ guint64 free_space;
- if (info->b_commiting) {
- _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command);
+ if (info->b_committing) {
+ MMCAM_LOG_ERROR("now on committing previous file!!(command : %d)", command);
return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
} else {
- _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
- info->b_commiting = TRUE;
+ MMCAM_LOG_INFO("_MMCamcorder_CMD_COMMIT : start");
+ info->b_committing = TRUE;
+ sc->bget_eos = FALSE;
}
for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
if (sc->audio_disable) {
/* check only video frame */
- if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
+ if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
+ hcamcorder->capture_in_recording == FALSE) {
break;
} else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
- _mmcam_dbg_err("Commit fail, frame count is %" G_GUINT64_FORMAT "",
- info->video_frame_count);
- info->b_commiting = FALSE;
- return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ MMCAM_LOG_ERROR("Commit fail, frame count is %"G_GUINT64_FORMAT", capturing %d",
+ info->video_frame_count, hcamcorder->capture_in_recording);
+
+ if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
+ MMCAM_LOG_WARNING("video frames are enough. keep going...");
+ } else {
+ info->b_committing = FALSE;
+ return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ }
} else {
- _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %" G_GUINT64_FORMAT "",
- count, info->video_frame_count);
+ MMCAM_LOG_WARNING("Waiting for enough video frame, retrial [%d], frame %"G_GUINT64_FORMAT", capturing %d",
+ count, info->video_frame_count, hcamcorder->capture_in_recording);
}
-
- usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
} else {
/* check both of video and audio frame */
- if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
+ if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
+ info->audio_frame_count &&
+ hcamcorder->capture_in_recording == FALSE) {
break;
} else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
- _mmcam_dbg_err("Commit fail, VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]",
- info->video_frame_count, info->audio_frame_count);
+ MMCAM_LOG_ERROR("Commit fail, VIDEO[%"G_GUINT64_FORMAT"], AUDIO [%"G_GUINT64_FORMAT"], capturing %d",
+ info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
+
+ if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
+ MMCAM_LOG_WARNING("video/audio frames are enough. keep going...");
+ } else {
+ info->b_committing = FALSE;
+ return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ }
- info->b_commiting = FALSE;
return MM_ERROR_CAMCORDER_INVALID_CONDITION;
} else {
- _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]",
- count, info->video_frame_count, info->audio_frame_count);
+ MMCAM_LOG_WARNING("Waiting for enough frames, retrial [%d], VIDEO[%"G_GUINT64_FORMAT"], AUDIO [%"G_GUINT64_FORMAT"], capturing %d",
+ count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
}
+ }
+ 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_LOG_WARNING("timeout");
+ } else {
usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
}
}
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hold-af-after-capturing", FALSE);
-
- if (sc->error_occurs) {
- GstPad *video= NULL;
- GstPad *audio = NULL;
- int ret = 0;
-
- _mmcam_dbg_err("Committing Error case");
-
- video = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "sink");
- ret = gst_pad_send_event (video, gst_event_new_eos());
- _mmcam_dbg_err("Sending EOS video sink : %d", ret);
- gst_object_unref(video);
-
- video = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
- gst_pad_push_event (video, gst_event_new_flush_start());
- gst_pad_push_event (video, gst_event_new_flush_stop());
- ret = gst_pad_push_event (video, gst_event_new_eos());
- _mmcam_dbg_err("Sending EOS video encoder src pad : %d", ret);
- gst_object_unref(video);
-
- if (sc->audio_disable == FALSE) {
- audio = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
- gst_pad_push_event (audio, gst_event_new_flush_start());
- gst_pad_push_event (audio, gst_event_new_flush_stop());
- ret = gst_element_send_event(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
- _mmcam_dbg_err("Sending EOS audio encoder src pad : %d", ret);
- gst_object_unref(audio);
- }
- } else {
- if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst != NULL) {
- ret = gst_element_send_event(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, gst_event_new_eos());
- _mmcam_dbg_warn("send eos to videosrc result : %d", ret);
- }
+ /* block push buffer */
+ info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
+ MMCAM_LOG_INFO("block push buffer to appsrc");
- if (sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
- pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
- ret = gst_element_send_event(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
- gst_object_unref(pad);
- pad = NULL;
+ _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
+ if (free_space < _MMCAMCORDER_MINIMUM_SPACE) {
+ MMCAM_LOG_WARNING("_MMCamcorder_CMD_COMMIT out of storage [%" G_GUINT64_FORMAT "]", free_space);
+ ret = MM_ERROR_OUT_OF_STORAGE;
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
- _mmcam_dbg_warn("send eos to audiosrc result : %d", ret);
+ if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
+ if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
+ MMCAM_LOG_WARNING("VIDEO: send eos to appsrc done");
+ } else {
+ MMCAM_LOG_ERROR("VIDEO: send EOS failed");
+ info->b_committing = FALSE;
+ ret = MM_ERROR_CAMCORDER_INTERNAL;
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
+ } else {
+ MMCAM_LOG_ERROR("No video stream source");
+ info->b_committing = FALSE;
+ ret = MM_ERROR_CAMCORDER_INTERNAL;
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
- if (hcamcorder->quick_device_close) {
- _mmcam_dbg_warn("quick_device_close");
- /* close device quickly */
- MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "quick-device-close",TRUE);
+ if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
+ if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
+ MMCAM_LOG_WARNING("AUDIO: send eos to audiosrc done");
+ } else {
+ MMCAM_LOG_ERROR("AUDIO: send EOS failed");
+ info->b_committing = FALSE;
+ ret = MM_ERROR_CAMCORDER_INTERNAL;
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+ } else {
+ MMCAM_LOG_INFO("No audio stream");
}
/* sc */
sc->previous_slot_time = 0;
/* Wait EOS */
- _mmcam_dbg_log("Start to wait EOS");
- ret =_mmcamcorder_get_eos_message(handle);
-
- /* set flush cache as FALSE */
- if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ITLV_JPEG_UYVY) {
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "flush-cache", FALSE);
- }
-
+ MMCAM_LOG_INFO("Start to wait EOS");
+ ret = _mmcamcorder_get_eos_message(handle);
if (ret != MM_ERROR_NONE) {
- info->b_commiting = FALSE;
+ info->b_committing = FALSE;
goto _ERR_CAMCORDER_VIDEO_COMMAND;
}
+
+ /* reset flag */
+ hcamcorder->capture_in_recording = FALSE;
}
break;
default:
return MM_ERROR_NONE;
_ERR_CAMCORDER_VIDEO_COMMAND:
- if (ret != MM_ERROR_NONE && sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst != NULL) {
- int op_status = 0;
- MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "operation-status", &op_status);
- _mmcam_dbg_err("Current Videosrc status[0x%x]", op_status);
- }
+ if (command == _MMCamcorder_CMD_RECORD)
+ _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
return ret;
}
int enabletag = 0;
guint64 file_size = 0;
- GstPad *pad = NULL;
- GstElement *pipeline = NULL;
-
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
_MMCamcorderSubContext *sc = NULL;
_MMCamcorderVideoInfo *info = NULL;
info = sc->info_video;
- _mmcam_dbg_err("");
-
- MMTA_ACUM_ITEM_BEGIN(" _mmcamcorder_video_handle_eos", 0);
+ MMCAM_LOG_ERROR("");
- pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ /* Play record stop sound */
+ _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
/* remove blocking part */
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
mm_camcorder_get_attributes(handle, NULL,
- MMCAM_TAG_ENABLE, &enabletag,
- NULL);
+ MMCAM_RECORDER_TAG_ENABLE, &enabletag,
+ NULL);
- _mmcam_dbg_log("Set state of pipeline as PAUSED");
- __ta__(" _MMCamcorder_CMD_COMMIT:GST_STATE_PAUSED",
- ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PAUSED);
- );
- if (ret != MM_ERROR_NONE) {
- _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:GST_STATE_READY or PAUSED failed. error[%x]", ret);
- }
+ ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
+ if (ret != MM_ERROR_NONE)
+ MMCAM_LOG_WARNING("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+ /* set recording hint */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
- __ta__(" _MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline",
- ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
- );
- if (ret != MM_ERROR_NONE) {
- _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
- }
+ /* stop video stream */
+ if (info->record_dual_stream) {
+ GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if (control) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
- if (enabletag && !(sc->ferror_send)) {
- __ta__( " _MMCamcorder_CMD_COMMIT:__mmcamcorder_add_locationinfo",
- ret = __mmcamcorder_add_locationinfo((MMHandleType)hcamcorder, info->fileformat);
- );
- if (ret) {
- _mmcam_dbg_log("Writing location information SUCCEEDED !!");
+ MMCAM_LOG_INFO("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
+ gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
} else {
- _mmcam_dbg_err("Writing location information FAILED !!");
+ MMCAM_LOG_ERROR("failed to get camera control");
}
}
+ if (enabletag && !(sc->ferror_send)) {
+ ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
+ MMCAM_LOG_INFO("Writing location information [%s] !!", ret ? "SUCCEEDED" : "FAILED");
+ }
+
/* Check file size */
if (info->max_size > 0) {
_mmcamcorder_get_file_size(info->filename, &file_size);
- _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
- info->max_size, file_size);
+ MMCAM_LOG_INFO("MAX size %"G_GUINT64_FORMAT" byte - created filesize %"G_GUINT64_FORMAT" byte",
+ info->max_size, file_size);
if (file_size > info->max_size) {
_MMCamcorderMsgItem message;
- _mmcam_dbg_err("File size is greater than max size !!");
+ MMCAM_LOG_ERROR("File size is greater than max size !!");
message.id = MM_MESSAGE_CAMCORDER_ERROR;
message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &message);
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
}
}
- /* Flush EOS event to avoid pending pipeline */
- _mmcam_dbg_log("Flush EOS event");
- pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "sink");
- gst_pad_push_event(pad, gst_event_new_flush_start());
- gst_pad_push_event(pad, gst_event_new_flush_stop());
- gst_object_unref(pad);
- pad = NULL;
-
- pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "src");
- gst_pad_push_event(pad, gst_event_new_flush_start());
- gst_pad_push_event(pad, gst_event_new_flush_stop());
- gst_object_unref(pad);
- pad = NULL;
-
- _mmcam_dbg_log("Set state as PLAYING");
- __ta__(" _MMCamcorder_CMD_COMMIT:GST_STATE_PLAYING",
- ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
- );
- /* Do not return when error is occurred.
- Recording file was created successfully, but starting pipeline failed */
- if (ret != MM_ERROR_NONE) {
- msg.id = MM_MESSAGE_CAMCORDER_ERROR;
- msg.param.code = ret;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
- _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
- }
+ if (info->restart_preview) {
+ /* block queue */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
- if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_ASM) {
- /* Play record stop sound */
- __ta__(" _MMCamcorder_CMD_COMMIT:_mmcamcorder_sound_solo_play",
- _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_FILEPATH_REC_STOP_SND, TRUE);
- );
+ MMCAM_LOG_INFO("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_LOG_ERROR("_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);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
+
+ if (ret != MM_ERROR_NONE) {
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = ret;
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
+ MMCAM_LOG_ERROR("Failed to set state READY[%x]", ret);
+ }
+
+ /* reset restart_preview for inset window layout */
+ info->restart_preview = FALSE;
+
+ /* recover preview size */
+ if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = MM_ERROR_CAMCORDER_INTERNAL;
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
+ MMCAM_LOG_ERROR("Failed to set camera resolution %dx%d",
+ info->preview_width, info->preview_height);
+ }
+
+ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
+ /* Do not return when error is occurred.
+ Recording file was created successfully, but starting pipeline failed */
+ if (ret != MM_ERROR_NONE) {
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = ret;
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
+ MMCAM_LOG_ERROR("Failed to set state PLAYING[%x]", ret);
+ }
} else {
- _mmcam_dbg_log("Do NOT play recording stop sound because of ASM stop");
+ MMCAM_LOG_INFO("No need to restart preview");
}
/* Send recording report to application */
msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
- report = (MMCamRecordingReport *)malloc(sizeof(MMCamRecordingReport));
- if (!report) {
- _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
- } else {
- report->recording_filename = strdup(info->filename);
- msg.param.data= report;
- msg.param.code = 1;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
- }
+ report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
+ report->recording_filename = g_strdup(info->filename);
+ msg.param.data = report;
+ msg.param.code = 1;
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
/* Finishing */
sc->pipeline_time = 0;
sc->pause_time = 0;
sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
sc->isMaxtimePausing = FALSE;
- sc->error_occurs = FALSE;
+ hcamcorder->error_occurs = FALSE;
info->video_frame_count = 0;
info->audio_frame_count = 0;
info->filesize = 0;
- g_free(info->filename);
- info->filename = NULL;
- info->b_commiting = FALSE;
+ info->b_committing = FALSE;
- MMTA_ACUM_ITEM_END(" _mmcamcorder_video_handle_eos", 0);
- MMTA_ACUM_ITEM_END("Real Commit Time", 0);
+ /* check recording stop sound */
+ _mmcamcorder_sound_solo_play_wait(handle);
- _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
+ MMCAM_LOG_ERROR("_MMCamcorder_CMD_COMMIT : end");
return TRUE;
}
-/**
- * This function is record video data probing function.
- * If this function is linked with certain pad by gst_pad_add_buffer_probe(),
- * this function will be called when data stream pass through the pad.
- *
- * @param[in] pad probing pad which calls this function.
- * @param[in] buffer buffer which contains stream data.
- * @param[in] u_data user data.
- * @return This function returns true on success, or false value with error
- * @remarks
- * @see
- */
-static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, gpointer u_data)
-{
- switch (GST_EVENT_TYPE(event)) {
- case GST_EVENT_UNKNOWN:
- /* upstream events */
- case GST_EVENT_QOS:
- case GST_EVENT_SEEK:
- case GST_EVENT_NAVIGATION:
- case GST_EVENT_LATENCY:
- /* downstream serialized events */
- case GST_EVENT_NEWSEGMENT :
- case GST_EVENT_TAG:
- case GST_EVENT_BUFFERSIZE:
- _mmcam_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
- break;
- case GST_EVENT_EOS:
- _mmcam_dbg_warn("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
- break;
- /* bidirectional events */
- case GST_EVENT_FLUSH_START:
- case GST_EVENT_FLUSH_STOP:
- _mmcam_dbg_err("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
- break;
- default:
- _mmcam_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
- break;
- }
-
- return TRUE;
-}
-
-
-static gboolean __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
{
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
+ GstMapInfo mapinfo;
_MMCamcorderSubContext *sc = NULL;
- _MMCamcorderVideoInfo *info = NULL;
+ _MMCamcorderVideoInfo *videoinfo = NULL;
+ _MMCamcorderMsgItem msg;
+ guint64 buffer_size = 0;
+ guint64 trailer_size = 0;
+ guint64 max_size = 0;
- mmf_return_val_if_fail(hcamcorder, TRUE);
- mmf_return_val_if_fail(buffer, FALSE);
+ mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
+ mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
- mmf_return_val_if_fail(sc && sc->info_video, TRUE);
- info = sc->info_video;
+ mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
+ videoinfo = sc->info_video;
+
+ /* get buffer size */
+ if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
+ MMCAM_LOG_WARNING("map failed : buffer %p", buffer);
+ return GST_PAD_PROBE_OK;
+ }
- /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/
+ buffer_size = mapinfo.size;
+ gst_buffer_unmap(buffer, &mapinfo);
- if (info->audio_frame_count == 0) {
- info->filesize += (guint64)GST_BUFFER_SIZE(buffer);
- info->audio_frame_count++;
- return TRUE;
+ g_mutex_lock(&videoinfo->size_check_lock);
+
+ if (videoinfo->audio_frame_count == 0) {
+ videoinfo->filesize += buffer_size;
+ videoinfo->audio_frame_count++;
+ 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");
+ MMCAM_LOG_WARNING("Recording is paused, drop frames");
+ g_mutex_unlock(&videoinfo->size_check_lock);
+ return GST_PAD_PROBE_DROP;
+ }
+
+ /* get trailer size */
+ if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
+ MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
+ else
+ trailer_size = 0;
+
+ /* check max size of recorded file */
+ max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
+ if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
+ GstState pipeline_state = GST_STATE_VOID_PENDING;
+ GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+
+ MMCAM_LOG_WARNING("Max size[%"G_GUINT64_FORMAT"], current size[%"G_GUINT64_FORMAT"],"\
+ " buffer size[%"G_GUINT64_FORMAT"], trailer size[%"G_GUINT64_FORMAT"]",
+ videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
+
+ if (!sc->isMaxsizePausing) {
+ sc->isMaxsizePausing = TRUE;
+ gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
+ if (pipeline_state == GST_STATE_PLAYING)
+ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+
+ msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
+ }
+
+ g_mutex_unlock(&videoinfo->size_check_lock);
+
return FALSE;
}
- info->filesize += (guint64)GST_BUFFER_SIZE(buffer);
- info->audio_frame_count++;
+ videoinfo->filesize += buffer_size;
+ videoinfo->audio_frame_count++;
- return TRUE;
+ MMCAM_LOG_DEBUG("video rec[%"GST_TIME_FORMAT"], size[%"G_GUINT64_FORMAT"(trailer:%"G_GUINT64_FORMAT")]",
+ GST_TIME_ARGS(GST_BUFFER_PTS(buffer)), videoinfo->filesize + trailer_size, trailer_size);
+
+ g_mutex_unlock(&videoinfo->size_check_lock);
+
+ return GST_PAD_PROBE_OK;
}
-static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+static GstPadProbeReturn __mmcamcorder_video_dataprobe_encoded(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
{
- static int count = 0;
gint ret = 0;
guint vq_size = 0;
guint aq_size = 0;
guint64 buffer_size = 0;
guint64 trailer_size = 0;
guint64 queued_buffer = 0;
- char *filename = NULL;
+ guint64 max_size = 0;
+ GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
+ GstMapInfo mapinfo;
+ storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
_MMCamcorderMsgItem msg;
_MMCamcorderSubContext *sc = NULL;
- _MMCamcorderVideoInfo *info = NULL;
+ _MMCamcorderVideoInfo *videoinfo = NULL;
- mmf_return_val_if_fail(hcamcorder, TRUE);
- mmf_return_val_if_fail(buffer, FALSE);
+ mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
+ mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
- mmf_return_val_if_fail(sc && sc->info_video, TRUE);
- info = sc->info_video;
+ mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
+ videoinfo = sc->info_video;
- /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/
if (sc->ferror_send) {
- _mmcam_dbg_warn("file write error, drop frames");
- return FALSE;
+ MMCAM_LOG_WARNING("file write error, drop frames");
+ return GST_PAD_PROBE_DROP;
}
- info->video_frame_count++;
- if (info->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
- /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
- info->video_frame_count); */
- info->filesize += (guint64)GST_BUFFER_SIZE(buffer);
- return TRUE;
+ gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
+ buffer_size = mapinfo.size;
+ gst_buffer_unmap(buffer, &mapinfo);
+
+ videoinfo->video_frame_count++;
+ if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
+ MMCAM_LOG_DEBUG("Pass minimum frame[%"G_GUINT64_FORMAT"]", videoinfo->video_frame_count);
+ g_mutex_lock(&videoinfo->size_check_lock);
+ videoinfo->filesize += buffer_size;
+ g_mutex_unlock(&videoinfo->size_check_lock);
+ return GST_PAD_PROBE_OK;
}
- buffer_size = GST_BUFFER_SIZE(buffer);
-
/* get trailer size */
- if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) {
- MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
- } else {
+ if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
+ MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
+ else
trailer_size = 0;
+
+ /* check free space */
+ ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
+ if (ret != 0) {
+ MMCAM_LOG_ERROR("Error occurred. [%d]", ret);
+ if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
+ sc->ferror_send = TRUE;
+
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = MM_ERROR_FILE_READ;
+
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
+ } else {
+ sc->ferror_count++;
+ }
+
+ return GST_PAD_PROBE_DROP; /* skip this buffer */
}
- /* to minimizing free space check overhead */
- count = count % _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL;
- if (count++ == 0) {
- filename = info->filename;
- ret = _mmcamcorder_get_freespace(filename, &free_space);
+ if (free_space == 0) {
+ /* check storage state */
+ storage_get_state(hcamcorder->storage_info.id, &storage_state);
+
+ MMCAM_LOG_WARNING("storage state %d", storage_state);
- /*_mmcam_dbg_log("check free space for recording");*/
+ if (storage_state == STORAGE_STATE_REMOVED ||
+ storage_state == STORAGE_STATE_UNMOUNTABLE) {
+ MMCAM_LOG_ERROR("storage was removed!");
+
+ _MMCAMCORDER_LOCK(hcamcorder);
+
+ if (sc->ferror_send == FALSE) {
+ MMCAM_LOG_ERROR("OUT_OF_STORAGE error");
- switch (ret) {
- case -2: /* file not exist */
- case -1: /* failed to get free space */
- _mmcam_dbg_err("Error occured. [%d]", ret);
- if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
sc->ferror_send = TRUE;
+
+ _MMCAMCORDER_UNLOCK(hcamcorder);
+
msg.id = MM_MESSAGE_CAMCORDER_ERROR;
- if (ret == -2) {
- msg.param.code = MM_ERROR_FILE_NOT_FOUND;
- } else {
- msg.param.code = MM_ERROR_FILE_READ;
- }
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ msg.param.code = MM_ERROR_OUT_OF_STORAGE;
+
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
} else {
- sc->ferror_count++;
+ _MMCAMCORDER_UNLOCK(hcamcorder);
+ MMCAM_LOG_WARNING("error was already sent");
}
- return FALSE; /* skip this buffer */
- break;
- default: /* succeeded to get free space */
- /* check free space for recording */
- /* get queued buffer size */
- if (sc->element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
- MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
- }
- if (sc->element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
- MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
- }
+ return GST_PAD_PROBE_DROP;
+ }
+ }
- queued_buffer = aq_size + vq_size;
+ /* get queued buffer size */
+ if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst)
+ MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
- /* check free space */
- if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
- _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
- _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
- " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
- free_space, trailer_size, buffer_size, queued_buffer);
+ if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst)
+ MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
- if (!sc->isMaxsizePausing) {
- MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
- sc->isMaxsizePausing = TRUE;
+ queued_buffer = aq_size + vq_size;
- msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
- }
+ if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
+ MMCAM_LOG_WARNING("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
+ " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
+ free_space, trailer_size, buffer_size, queued_buffer);
- return FALSE;
- }
- break;
+ if (!sc->isMaxsizePausing) {
+ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ sc->isMaxsizePausing = TRUE;
+
+ msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
}
+
+ return GST_PAD_PROBE_DROP;
}
+ g_mutex_lock(&videoinfo->size_check_lock);
+
/* check max size of recorded file */
- if (info->max_size > 0 &&
- info->max_size < info->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE) {
+ max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
+ if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
GstState pipeline_state = GST_STATE_VOID_PENDING;
GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
- _mmcam_dbg_warn("Max size!!! Recording is paused.");
- _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
- " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
- info->max_size, info->filesize, buffer_size, trailer_size);
+
+ MMCAM_LOG_WARNING("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
+ " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
+ videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
if (!sc->isMaxsizePausing) {
+ sc->isMaxsizePausing = TRUE;
gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
- if (pipeline_state == GST_STATE_PLAYING) {
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
- sc->isMaxsizePausing = TRUE;
- }
+ if (pipeline_state == GST_STATE_PLAYING)
+ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
}
- return FALSE;
+ g_mutex_unlock(&videoinfo->size_check_lock);
+
+ return GST_PAD_PROBE_DROP;
}
- info->filesize += (guint64)buffer_size;
+ videoinfo->filesize += (guint64)buffer_size;
- _mmcam_dbg_log("filesize %lld Byte, ", info->filesize);
+ MMCAM_LOG_DEBUG("video rec[%"GST_TIME_FORMAT"], size[%"G_GUINT64_FORMAT"(trailer:%"G_GUINT64_FORMAT")]",
+ GST_TIME_ARGS(GST_BUFFER_PTS(buffer)), videoinfo->filesize + trailer_size, trailer_size);
- return TRUE;
+ g_mutex_unlock(&videoinfo->size_check_lock);
+
+ return GST_PAD_PROBE_OK;
}
-static gboolean __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
{
guint64 trailer_size = 0;
guint64 rec_pipe_time = 0;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
_MMCamcorderMsgItem msg;
_MMCamcorderSubContext *sc = NULL;
- _MMCamcorderVideoInfo *info = NULL;
+ _MMCamcorderVideoInfo *videoinfo = NULL;
- mmf_return_val_if_fail(buffer, FALSE);
- mmf_return_val_if_fail(hcamcorder, TRUE);
+ GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
+
+ mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
+ mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
- mmf_return_val_if_fail(sc, TRUE);
- mmf_return_val_if_fail(sc->info_video, TRUE);
+ mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
+ mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
- info = sc->info_video;
+ videoinfo = sc->info_video;
- b_time = GST_BUFFER_TIMESTAMP(buffer);
+ b_time = GST_BUFFER_PTS(buffer);
rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
- if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) {
- MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
- } else {
+ if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
+ MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
+ else
trailer_size = 0;
- }
/* check max time */
- if (info->max_time > 0 && rec_pipe_time > info->max_time) {
- _mmcam_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", \
- rec_pipe_time, info->max_time);
+ if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
+ MMCAM_LOG_WARNING("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
+ rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
if (!sc->isMaxtimePausing) {
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
sc->isMaxtimePausing = TRUE;
msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
- msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10);
+ msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
msg.param.recording_status.remained_time = 0;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
}
- return FALSE;
+ return GST_PAD_PROBE_DROP;
}
/* calculate remained time can be recorded */
- if (info->max_time > 0 && info->max_time < (remained_time + rec_pipe_time)) {
- remained_time = info->max_time - rec_pipe_time;
- } else if (info->max_size > 0) {
- long double max_size = (long double)info->max_size;
- long double current_size = (long double)(info->filesize + trailer_size);
+ if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
+ remained_time = videoinfo->max_time - rec_pipe_time;
+ } else if (videoinfo->max_size > 0) {
+ long double max_size = (long double)videoinfo->max_size;
+ long double current_size = (long double)(videoinfo->filesize + trailer_size);
remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
}
msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
- msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10);
+ msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
msg.param.recording_status.remained_time = remained_time;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
- _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
- GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
+ if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
+ guint record_motion_rate = (guint)videoinfo->record_motion_rate;
- if (info->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
- GST_BUFFER_TIMESTAMP(buffer) = b_time * (info->record_timestamp_ratio);
+ MMCAM_LOG_VERBOSE("record_motion_rate[%u], videoinfo->record_drop_count[%u]",
+ record_motion_rate, videoinfo->record_drop_count);
+
+ /* drop some frame if fast motion */
+ if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
+ if (record_motion_rate != (videoinfo->record_drop_count++)) {
+ MMCAM_LOG_VERBOSE("drop frame");
+ return GST_PAD_PROBE_DROP;
+ }
+
+ videoinfo->record_drop_count = 1;
+ MMCAM_LOG_VERBOSE("pass frame");
+ }
+
+ GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
+ GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
}
- return TRUE;
+ return GST_PAD_PROBE_OK;
}
-static gboolean __mmcamcorder_audioque_dataprobe(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
{
_MMCamcorderMsgItem msg;
guint64 trailer_size = 0;
guint64 rec_pipe_time = 0;
_MMCamcorderSubContext *sc = NULL;
- GstElement *pipeline = NULL;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
- _MMCamcorderVideoInfo *info = NULL;
+ _MMCamcorderVideoInfo *videoinfo = NULL;
unsigned int remained_time = 0;
+ GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
- mmf_return_val_if_fail(buffer, FALSE);
- mmf_return_val_if_fail(hcamcorder, TRUE);
+ mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
+ mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
- mmf_return_val_if_fail(sc, TRUE);
- mmf_return_val_if_fail(sc->info_video, TRUE);
- mmf_return_val_if_fail(sc->element, TRUE);
+ mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
+ mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
+ mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
- info = sc->info_video;
- pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ videoinfo = sc->info_video;
- if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_TIMESTAMP(buffer))) {
- _mmcam_dbg_err( "Buffer timestamp is invalid, check it");
- return TRUE;
+ if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
+ MMCAM_LOG_ERROR("Buffer timestamp is invalid, check it");
+ return GST_PAD_PROBE_OK;
}
- rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_TIMESTAMP(buffer));
+ rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
- if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) {
- MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
- } else {
+ if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
+ MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
+ else
trailer_size = 0;
- }
/* calculate remained time can be recorded */
- if (info->max_time > 0 && info->max_time < (remained_time + rec_pipe_time)) {
- remained_time = info->max_time - rec_pipe_time;
- } else if (info->max_size > 0) {
- long double max_size = (long double)info->max_size;
- long double current_size = (long double)(info->filesize + trailer_size);
+ if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
+ remained_time = videoinfo->max_time - rec_pipe_time;
+ } else if (videoinfo->max_size > 0) {
+ long double max_size = (long double)videoinfo->max_size;
+ long double current_size = (long double)(videoinfo->filesize + trailer_size);
remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
}
- if (info->max_time > 0 && rec_pipe_time > info->max_time) {
- _mmcam_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", \
- rec_pipe_time, info->max_time);
+ if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
+ MMCAM_LOG_WARNING("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
+ rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
if (!sc->isMaxtimePausing) {
- MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
sc->isMaxtimePausing = TRUE;
msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
- msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10);
+ msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
msg.param.recording_status.remained_time = 0;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
}
- return FALSE;
+ return GST_PAD_PROBE_DROP;
}
msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
- msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10);
+ msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
msg.param.recording_status.remained_time = remained_time;
- _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
- _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
- GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
+ MMCAM_LOG_DEBUG("audio data probe[%" GST_TIME_FORMAT "], size[%"G_GUINT64_FORMAT"]",
+ GST_TIME_ARGS(GST_BUFFER_PTS(buffer)), videoinfo->filesize + trailer_size);
- return TRUE;
+ return GST_PAD_PROBE_OK;
}
-static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
{
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
double volume = 0.0;
int channel = 0;
int err = MM_ERROR_UNKNOWN;
char *err_name = NULL;
+ GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
+ GstMapInfo mapinfo;
- mmf_return_val_if_fail(buffer, FALSE);
- mmf_return_val_if_fail(hcamcorder, FALSE);
+ mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
+ mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
- /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/
err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
- MMCAM_AUDIO_VOLUME, &volume,
- MMCAM_AUDIO_FORMAT, &format,
- MMCAM_AUDIO_CHANNEL, &channel,
- NULL);
+ MMCAM_AUDIO_VOLUME, &volume,
+ MMCAM_AUDIO_FORMAT, &format,
+ MMCAM_AUDIO_CHANNEL, &channel,
+ NULL);
if (err != MM_ERROR_NONE) {
- _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ MMCAM_LOG_WARNING("Get attrs fail. (%s:%x)", err_name, err);
SAFE_FREE(err_name);
return err;
}
+ memset(&mapinfo, 0x0, sizeof(GstMapInfo));
+
+ gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
+
/* Set audio stream NULL */
- if (volume == 0.0) {
- memset(GST_BUFFER_DATA(buffer), 0, GST_BUFFER_SIZE(buffer));
- }
+ if (volume == 0.0)
+ memset(mapinfo.data, 0, mapinfo.size);
+
+ MMCAM_LOG_DEBUG("audio stream[%"GST_TIME_FORMAT"] - cb[%p], fmt[%d], ch[%d], size[%"G_GSIZE_FORMAT"]",
+ GST_TIME_ARGS(GST_BUFFER_PTS(buffer)), hcamcorder->astream_cb, format, channel, mapinfo.size);
/* CALL audio stream callback */
- if (hcamcorder->astream_cb && buffer && GST_BUFFER_DATA(buffer)) {
+ if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
MMCamcorderAudioStreamDataType stream;
if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
- _mmcam_dbg_warn("Not ready for stream callback");
- return TRUE;
+ MMCAM_LOG_WARNING("Not ready for stream callback");
+ gst_buffer_unmap(buffer, &mapinfo);
+ return GST_PAD_PROBE_OK;
}
- /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
- GST_BUFFER_DATA(buffer), width, height, format);*/
-
- stream.data = (void *)GST_BUFFER_DATA(buffer);
+ stream.data = (void *)mapinfo.data;
stream.format = format;
stream.channel = channel;
- stream.length = GST_BUFFER_SIZE(buffer);
- stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); /* nano -> milli second */
+ stream.length = mapinfo.size;
+ stream.timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer)));
_MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
- if (hcamcorder->astream_cb) {
+ if (hcamcorder->astream_cb)
hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
- }
_MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
}
- return TRUE;
+ gst_buffer_unmap(buffer, &mapinfo);
+
+ return GST_PAD_PROBE_OK;
}
-static gboolean __mmcamcorder_add_locationinfo(MMHandleType handle, int fileformat)
+static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
{
gboolean bret = FALSE;
switch (fileformat) {
case MM_FILE_FORMAT_3GP:
case MM_FILE_FORMAT_MP4:
- bret = __mmcamcorder_add_locationinfo_mp4(handle);
+ bret = __mmcamcorder_add_metadata_mp4(handle);
break;
default:
- _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
+ MMCAM_LOG_WARNING("Unsupported fileformat to insert location info (%d)", fileformat);
break;
}
}
-static gboolean __mmcamcorder_add_locationinfo_mp4(MMHandleType handle)
+static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
{
FILE *f = NULL;
guchar buf[4];
gdouble altitude = 0;
int err = 0;
int orientation = 0;
+ int gps_enable = 0;
char *err_name = NULL;
char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
- _MMCamcorderLocationInfo location_info = {0,};
+ _MMCamcorderLocationInfo location_info = {0, 0, 0};
+ _MMCamcorderLocationInfo geo_info = {0, 0, 0};
_MMCamcorderVideoInfo *info = NULL;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
- _mmcam_dbg_log("");
+ MMCAM_LOG_INFO("");
info = sc->info_video;
- f = fopen(info->filename, "rb+");
+ f = fopen64(info->filename, "rb+");
if (f == NULL) {
strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
- _mmcam_dbg_err("file open failed [%s]", err_msg);
+ MMCAM_LOG_ERROR("file open failed [%s]", err_msg);
return FALSE;
}
mm_camcorder_get_attributes(handle, &err_name,
- MMCAM_TAG_LATITUDE, &latitude,
- MMCAM_TAG_LONGITUDE, &longitude,
- MMCAM_TAG_ALTITUDE, &altitude,
- MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
- NULL);
+ MMCAM_TAG_LATITUDE, &latitude,
+ MMCAM_TAG_LONGITUDE, &longitude,
+ MMCAM_TAG_ALTITUDE, &altitude,
+ MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
+ MMCAM_TAG_GPS_ENABLE, &gps_enable,
+ NULL);
if (err_name) {
- _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
- SAFE_FREE (err_name);
+ MMCAM_LOG_WARNING("Get tag attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE(err_name);
}
location_info.longitude = _mmcamcorder_double_to_fix(longitude);
location_info.latitude = _mmcamcorder_double_to_fix(latitude);
location_info.altitude = _mmcamcorder_double_to_fix(altitude);
-
+ geo_info.longitude = longitude *10000;
+ geo_info.latitude = latitude *10000;
+ geo_info.altitude = altitude *10000;
/* find udta container.
if, there are udta container, write loci box after that
else, make udta container and write loci box. */
- if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('u','d','t','a'), TRUE)) {
+ if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
size_t nread = 0;
- _mmcam_dbg_log("find udta container");
+ MMCAM_LOG_INFO("find udta container");
/* read size */
- if (fseek(f, -8L, SEEK_CUR) != 0) {
+ if (fseek(f, -8L, SEEK_CUR) != 0)
goto fail;
- }
- udta_pos = ftell(f);
- if (udta_pos < 0) {
+ udta_pos = ftello(f);
+ if (udta_pos < 0)
goto ftell_fail;
- }
nread = fread(&buf, sizeof(char), sizeof(buf), f);
- _mmcam_dbg_log("recorded file fread %d", nread);
+ MMCAM_LOG_INFO("recorded file fread %zu", nread);
udta_size = _mmcamcorder_get_container_size(buf);
/* goto end of udta and write 'loci' box */
- if (fseek(f, (udta_size-4L), SEEK_CUR) != 0) {
+ if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
goto fail;
- }
- if (!_mmcamcorder_write_loci(f, location_info)) {
- goto fail;
+ if (gps_enable) {
+ if (!_mmcamcorder_write_loci(f, location_info)) {
+ MMCAM_LOG_ERROR("failed to write loci");
+ goto fail;
+ }
+
+ if (!_mmcamcorder_write_geodata(f, geo_info)) {
+ MMCAM_LOG_ERROR("failed to write geodata");
+ goto fail;
+ }
}
- current_pos = ftell(f);
- if (current_pos < 0) {
+ current_pos = ftello(f);
+ if (current_pos < 0)
goto ftell_fail;
- }
- if (!_mmcamcorder_update_size(f, udta_pos, current_pos)) {
+ if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
goto fail;
- }
} else {
- _mmcam_dbg_log("No udta container");
- if (fseek(f, 0, SEEK_END) != 0) {
+ MMCAM_LOG_INFO("No udta container");
+ if (fseek(f, 0, SEEK_END) != 0)
goto fail;
- }
- if (!_mmcamcorder_write_udta(f, location_info)) {
+ if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
+ MMCAM_LOG_ERROR("failed to write udta");
goto fail;
}
}
/* find moov container.
update moov container size. */
- if((current_pos = ftell(f))<0)
+ if ((current_pos = ftello(f)) < 0)
goto ftell_fail;
- if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m','o','o','v'), TRUE)) {
- gint64 internal_pos = ftell(f);
+ if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
+ gint64 internal_pos = ftello(f);
- _mmcam_dbg_log("found moov container");
- if (fseek(f, -8L, SEEK_CUR) !=0) {
+ MMCAM_LOG_INFO("found moov container");
+ if (fseek(f, -8L, SEEK_CUR) != 0)
goto fail;
- }
- moov_pos = ftell(f);
- if (moov_pos < 0) {
+ moov_pos = ftello(f);
+ if (moov_pos < 0)
goto ftell_fail;
- }
- if (!_mmcamcorder_update_size(f, moov_pos, current_pos)) {
+ if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
goto fail;
- }
/* add orientation info */
- fseek(f, internal_pos, SEEK_SET);
- if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t','r','a','k'), FALSE)) {
- _mmcam_dbg_err("failed to find [trak] tag");
+ if (fseeko(f, internal_pos, SEEK_SET) < 0) {
+ MMCAM_LOG_ERROR("fseeko failed : errno %d", errno);
+ goto fail;
+ }
+
+ if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
+ MMCAM_LOG_ERROR("failed to find [trak] tag");
goto fail;
}
- if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t','k','h','d'), FALSE)) {
- _mmcam_dbg_err("failed to find [tkhd] tag");
+ if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
+ MMCAM_LOG_ERROR("failed to find [tkhd] tag");
goto fail;
}
- _mmcam_dbg_log("found [tkhd] tag");
+ MMCAM_LOG_INFO("found [tkhd] tag");
/* seek to start position of composition matrix */
- fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR);
-
- /* update composition matrix for orientation */
- _mmcamcorder_update_composition_matrix(f, orientation);
+ if (fseek(f, OFFSET_COMPOSITION_MATRIX, SEEK_CUR) == 0) {
+ /* update composition matrix for orientation */
+ _mmcamcorder_update_composition_matrix(f, orientation);
+ } else {
+ MMCAM_LOG_ERROR("fseek failed : errno %d", errno);
+ goto fail;
+ }
} else {
- _mmcam_dbg_err("No 'moov' container");
+ MMCAM_LOG_ERROR("No 'moov' container");
goto fail;
}
return FALSE;
ftell_fail:
- _mmcam_dbg_err("ftell() returns negative value.");
+ MMCAM_LOG_ERROR("ftell() returns negative value.");
fclose(f);
return FALSE;
}
+
+
+int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
+{
+ 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 && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ /* check video source element */
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
+ MMCAM_LOG_WARNING("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
+ MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
+ _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
+ G_CALLBACK(__mmcamcorder_video_stream_cb),
+ hcamcorder);
+ return MM_ERROR_NONE;
+ } else {
+ MMCAM_LOG_ERROR("videosrc element is not created yet");
+ return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ }
+}
+
+
+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;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ 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->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ info = sc->info_video;
+
+ MMCAM_LOG_WARNING("start");
+
+ /* create encoding pipeline */
+ ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
+ if (ret != MM_ERROR_NONE)
+ goto _ERR_PREPARE_RECORD;
+
+ 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_LOG_ERROR("strdup[src:%p] was failed", temp_filename);
+ goto _ERR_PREPARE_RECORD;
+ }
+
+ MMCAM_LOG_INFO("Record file name [%s]", info->filename);
+ MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
+ } else {
+ MMCAM_LOG_INFO("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(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
+
+ /* Adjust display FPS */
+ sc->display_interval = 0;
+ sc->previous_slot_time = 0;
+
+ ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
+ if (ret != MM_ERROR_NONE)
+ goto _ERR_PREPARE_RECORD;
+
+ MMCAM_LOG_WARNING("done");
+
+ return ret;
+
+_ERR_PREPARE_RECORD:
+ /* Remove recorder pipeline and recording file which size maybe zero */
+ _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
+ if (info && info->filename) {
+ MMCAM_LOG_INFO("file delete(%s)", info->filename);
+ unlink(info->filename);
+ }
+
+ return ret;
+}