4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jeongmo Yang <jm80.yang@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 /*=======================================================================================
24 =======================================================================================*/
25 #include <gst/video/cameracontrol.h>
26 #include <gst/app/gstappsrc.h>
27 #include "mm_camcorder_internal.h"
28 #include "mm_camcorder_videorec.h"
30 /*---------------------------------------------------------------------------------------
31 | GLOBAL VARIABLE DEFINITIONS for internal |
32 ---------------------------------------------------------------------------------------*/
33 #define _MMCAMCORDER_LOCATION_INFO /* for add gps information */
34 #define MAX_ERROR_MESSAGE_LEN 128
36 /*---------------------------------------------------------------------------------------
37 | LOCAL VARIABLE DEFINITIONS for internal |
38 ---------------------------------------------------------------------------------------*/
39 #define _MMCAMCORDER_MINIMUM_FRAME 5
40 #define _MMCAMCORDER_RETRIAL_COUNT 10
41 #define _MMCAMCORDER_FRAME_WAIT_TIME 200000 /* ms */
42 #define _OFFSET_COMPOSITION_MATRIX 40L
43 #define _GOP_GEN_INTERVAL 1000000000 /*nano seconds*/
44 #define _MMCAMCORDER_VIDEO_MINIMUM_SPACE (_MMCAMCORDER_MINIMUM_SPACE << 1) /* byte */
46 /*---------------------------------------------------------------------------------------
47 | LOCAL FUNCTION PROTOTYPES: |
48 ---------------------------------------------------------------------------------------*/
49 /* STATIC INTERNAL FUNCTION */
50 static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data);
51 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
52 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
53 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
54 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
55 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
56 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat);
57 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle);
59 /*=======================================================================================
60 | FUNCTION DEFINITIONS |
61 =======================================================================================*/
62 /*---------------------------------------------------------------------------------------
63 | GLOBAL FUNCTION DEFINITIONS: |
64 ---------------------------------------------------------------------------------------*/
65 static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
67 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
68 _MMCamcorderSubContext *sc = NULL;
70 GstBuffer *buffer = gst_sample_get_buffer(sample);
71 mmf_return_val_if_fail(buffer, FALSE);
72 mmf_return_val_if_fail(gst_buffer_n_memory(buffer), FALSE);
73 mmf_return_val_if_fail(hcamcorder, FALSE);
75 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
76 mmf_return_val_if_fail(sc, FALSE);
79 _mmcam_dbg_log("ENTER - push_encoding_buffer %d, buffer %p, MALLOCDATA %p, size %d",
80 sc->info_video->push_encoding_buffer, buffer, GST_BUFFER_MALLOCDATA(buffer), GST_BUFFER_SIZE(buffer));
83 /* push buffer in appsrc to encode */
84 if (sc->info_video->push_encoding_buffer == PUSH_ENCODING_BUFFER_RUN &&
85 sc->info_video->record_dual_stream &&
86 sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst) {
87 GstFlowReturn ret = 0;
88 GstClock *pipe_clock = NULL;
90 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst) {
91 if (sc->info_video->is_firstframe) {
92 sc->info_video->is_firstframe = FALSE;
93 pipe_clock = GST_ELEMENT_CLOCK(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst);
95 gst_object_ref(pipe_clock);
96 sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer) - (gst_clock_get_time(pipe_clock) - GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time);
97 gst_object_unref(pipe_clock);
101 if (sc->info_video->is_firstframe) {
102 sc->info_video->is_firstframe = FALSE;
103 sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer);
107 GST_BUFFER_PTS(buffer) = GST_BUFFER_PTS(buffer) - sc->info_video->base_video_ts;
108 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
110 ret = gst_app_src_push_buffer((GstAppSrc *)sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, buffer);
111 if (ret != GST_FLOW_OK && ret != GST_FLOW_FLUSHING) {
112 _mmcam_dbg_err("gst_app_src_push_buffer failed [0x%x]", ret);
113 gst_buffer_unref(buffer);
117 /*_mmcam_dbg_log("push buffer result : 0x%x", ret);*/
119 _mmcam_dbg_warn("unref video buffer immediately - push encoding buffer %d",
120 sc->info_video->push_encoding_buffer);
122 gst_buffer_unref(buffer);
130 int _mmcamcorder_create_recorder_pipeline(MMHandleType handle)
133 int err = MM_ERROR_NONE;
134 const char* gst_element_rsink_name = NULL;
137 GstPad *srcpad = NULL;
138 GstPad *sinkpad = NULL;
140 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
141 _MMCamcorderSubContext *sc = NULL;
143 type_element *RecordsinkElement = NULL;
145 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
147 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
148 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
149 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
151 _mmcam_dbg_warn("start");
153 err = _mmcamcorder_check_videocodec_fileformat_compatibility(handle);
154 if (err != MM_ERROR_NONE)
158 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
159 _mmcam_dbg_log("pipeline is exist so need to remove pipeline _MMCAMCORDER_ENCODE_MAIN_PIPE = %p",
160 sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
161 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
164 _MMCAMCORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
166 /* get audio disable */
167 mm_camcorder_get_attributes(handle, NULL,
168 MMCAM_AUDIO_DISABLE, &sc->audio_disable,
171 _mmcam_dbg_log("MMCAM_AUDIO_DISABLE %d, is_modified_rate %d",
172 sc->audio_disable, sc->is_modified_rate);
174 sc->audio_disable |= sc->is_modified_rate;
176 if (sc->audio_disable == FALSE) {
177 /* create audiosrc bin */
178 err = _mmcamcorder_create_audiosrc_bin((MMHandleType)hcamcorder);
179 if (err != MM_ERROR_NONE)
183 err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder, MM_CAMCORDER_ENCBIN_PROFILE_VIDEO);
184 if (err != MM_ERROR_NONE)
187 if (sc->audio_disable == FALSE) {
188 gst_bin_add(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
189 sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
192 /* add element and encodesink bin to encode main pipeline */
193 gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
194 sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst,
195 sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst,
196 sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
199 /* Link each element : appsrc - capsfilter - encodesink bin */
200 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "src");
201 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "sink");
202 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
204 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "src");
205 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
206 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
208 if (sc->audio_disable == FALSE) {
209 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
210 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
211 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
214 _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
215 CONFIGURE_CATEGORY_MAIN_RECORD,
218 _mmcamcorder_conf_get_value_element_name(RecordsinkElement, &gst_element_rsink_name);
220 if (!gst_element_rsink_name) {
221 _mmcam_dbg_err("failed to get recordsink name");
222 err = MM_ERROR_CAMCORDER_INTERNAL;
223 goto pipeline_creation_error;
226 /* set data probe function */
228 /* register message cb */
230 /* set data probe functions */
231 if (sc->audio_disable == FALSE) {
232 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "sink");
233 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
234 __mmcamcorder_audioque_dataprobe, hcamcorder);
235 gst_object_unref(sinkpad);
239 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
240 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
241 __mmcamcorder_audio_dataprobe_audio_mute, hcamcorder);
242 gst_object_unref(srcpad);
245 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
246 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "src");
247 MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
248 __mmcamcorder_eventprobe_monitor, hcamcorder);
249 gst_object_unref(srcpad);
254 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
255 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "src");
256 MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
257 __mmcamcorder_eventprobe_monitor, hcamcorder);
258 gst_object_unref(srcpad);
262 if (sc->audio_disable) {
263 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "sink");
264 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
265 __mmcamcorder_video_dataprobe_audio_disable, hcamcorder);
266 gst_object_unref(sinkpad);
270 if (!strcmp(gst_element_rsink_name, "filesink")) {
271 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
272 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
273 __mmcamcorder_video_dataprobe_record, hcamcorder);
274 gst_object_unref(srcpad);
277 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
278 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
279 __mmcamcorder_audio_dataprobe_check, hcamcorder);
280 gst_object_unref(srcpad);
284 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "sink");
285 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
286 __mmcamcorder_muxed_dataprobe, hcamcorder);
287 MMCAMCORDER_ADD_EVENT_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
288 __mmcamcorder_eventprobe_monitor, hcamcorder);
289 gst_object_unref(sinkpad);
292 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
294 /* register pipeline message callback */
295 hcamcorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder);
297 /* set sync handler */
298 gst_bus_set_sync_handler(bus, _mmcamcorder_encode_pipeline_bus_sync_callback, (gpointer)hcamcorder, NULL);
300 gst_object_unref(bus);
303 return MM_ERROR_NONE;
305 pipeline_creation_error:
306 for (i = _MMCAMCORDER_AUDIOSRC_BIN ; i <= _MMCAMCORDER_ENCSINK_SINK ; i++)
307 _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, i);
309 _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE);
314 int _mmcamcorder_remove_audio_pipeline(MMHandleType handle)
316 GstPad *srcpad = NULL;
317 GstPad *sinkpad = NULL;
318 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
319 _MMCamcorderSubContext *sc = NULL;
321 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
323 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
324 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
325 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
329 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst != NULL) {
330 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
331 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
332 _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
334 /* release audiosrc bin */
335 gst_bin_remove(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
336 sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
339 To avoid conflicting between old elements and newly created elements,
340 I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
341 This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
342 So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
343 It's because the pipeline of audio recording destroys at the same time,
344 and '_mmcamcorder_element_release_noti' will perfom removing handle.
346 _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element, _MMCAMCORDER_AUDIOSRC_BIN, _MMCAMCORDER_AUDIOSRC_VOL);
348 _mmcam_dbg_log("Audio pipeline removed");
351 return MM_ERROR_NONE;
355 int _mmcamcorder_remove_encode_pipeline(MMHandleType handle)
357 GstPad *reqpad = NULL;
358 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
359 _MMCamcorderSubContext *sc = NULL;
360 #ifdef _MMCAMCORDER_MM_RM_SUPPORT
361 int ret = MM_ERROR_NONE;
362 #endif /* _MMCAMCORDER_MM_RM_SUPPORT */
364 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
366 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
367 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
368 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
372 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst != NULL) {
373 /* release request pad */
374 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
376 gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
377 gst_object_unref(reqpad);
381 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
383 gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
384 gst_object_unref(reqpad);
388 /* release encode main pipeline */
389 gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
392 To avoid conflicting between old elements and newly created elements,
393 I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
394 This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
395 So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
396 It's because the pipeline of audio recording destroys at the same time,
397 and '_mmcamcorder_element_release_noti' will perfom removing handle.
399 /* _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element,
400 _MMCAMCORDER_ENCODE_MAIN_PIPE, _MMCAMCORDER_ENCSINK_SINK); */
402 _mmcam_dbg_warn("Encoder pipeline removed");
404 #ifdef _MMCAMCORDER_MM_RM_SUPPORT
405 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
407 _mmcam_dbg_warn("lock resource - cb calling %d", hcamcorder->is_release_cb_calling);
409 if (hcamcorder->is_release_cb_calling == FALSE) {
410 /* release resource */
411 ret = mm_resource_manager_mark_for_release(hcamcorder->resource_manager,
412 hcamcorder->video_encoder_resource);
413 if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
414 hcamcorder->video_encoder_resource = NULL;
416 _mmcam_dbg_warn("mark resource for release 0x%x", ret);
418 ret = mm_resource_manager_commit(hcamcorder->resource_manager);
420 _mmcam_dbg_warn("commit resource release 0x%x", ret);
423 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
425 _mmcam_dbg_warn("unlock resource");
426 #endif /* _MMCAMCORDER_MM_RM_SUPPORT */
429 return MM_ERROR_NONE;
433 int _mmcamcorder_remove_recorder_pipeline(MMHandleType handle)
435 int ret = MM_ERROR_NONE;
436 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
437 _MMCamcorderSubContext *sc = NULL;
441 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
442 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
443 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
445 _mmcam_dbg_log("start");
447 if (!sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
448 _mmcam_dbg_warn("pipeline is not existed.");
449 return MM_ERROR_NONE;
452 _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_VIDEOREC);
454 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
455 if (ret != MM_ERROR_NONE) {
456 _mmcam_dbg_err("Faile to change encode main pipeline [0x%x]", ret);
460 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
462 /* remove audio pipeline first */
463 ret = _mmcamcorder_remove_audio_pipeline(handle);
464 if (ret != MM_ERROR_NONE) {
465 _mmcam_dbg_err("Fail to remove audio pipeline");
469 ret = _mmcamcorder_remove_encode_pipeline(handle);
470 if (ret != MM_ERROR_NONE) {
471 _mmcam_dbg_err("Fail to remove encoder pipeline");
475 /* Remove pipeline message callback */
476 if (hcamcorder->encode_pipeline_cb_event_id != 0) {
477 g_source_remove(hcamcorder->encode_pipeline_cb_event_id);
478 hcamcorder->encode_pipeline_cb_event_id = 0;
481 /* Remove remained message */
483 GstMessage *gst_msg = NULL;
484 while ((gst_msg = gst_bus_pop(bus)) != NULL) {
485 _mmcamcorder_pipeline_cb_message(bus, gst_msg, (gpointer)hcamcorder);
486 gst_message_unref(gst_msg);
489 gst_object_unref(bus);
493 _mmcam_dbg_log("done");
499 int _mmcamcorder_video_command(MMHandleType handle, int command)
504 int ret = MM_ERROR_NONE;
505 double motion_rate = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
506 char *err_name = NULL;
507 char *temp_filename = NULL;
508 GstCameraControl *CameraControl = NULL;
509 GstCameraControlChannel *CameraControlChannel = NULL;
510 const GList *controls = NULL;
511 const GList *item = NULL;
514 GstElement *pipeline = NULL;
516 _MMCamcorderVideoInfo *info = NULL;
517 _MMCamcorderSubContext *sc = NULL;
518 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
520 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
522 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
523 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
524 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
525 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
527 info = sc->info_video;
529 _mmcam_dbg_log("Command(%d)", command);
531 pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
534 case _MMCamcorder_CMD_RECORD:
536 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED) {
542 int ret_free_space = 0;
543 char *dir_name = NULL;
544 guint64 free_space = 0;
545 int file_system_type = 0;
546 int root_directory_length = 0;
549 _mmcam_dbg_log("Record Start - dual stream %d", info->support_dual_stream);
551 #ifdef _MMCAMCORDER_MM_RM_SUPPORT
552 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
554 /* prepare resource manager for H/W encoder */
555 if (hcamcorder->video_encoder_resource == NULL) {
556 ret = mm_resource_manager_mark_for_acquire(hcamcorder->resource_manager,
557 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_ENCODER,
558 MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
559 &hcamcorder->video_encoder_resource);
560 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
561 _mmcam_dbg_err("could not prepare for encoder resource");
562 ret = MM_ERROR_CAMCORDER_INTERNAL;
563 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
564 goto _ERR_CAMCORDER_VIDEO_COMMAND;
567 _mmcam_dbg_log("encoder already acquired");
570 /* acquire resources */
571 ret = mm_resource_manager_commit(hcamcorder->resource_manager);
572 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
573 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
575 _mmcam_dbg_err("could not acquire resources");
577 goto _ERR_CAMCORDER_VIDEO_COMMAND;
580 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
581 #endif /* _MMCAMCORDER_MM_RM_SUPPORT */
583 /* init record_dual_stream */
584 info->record_dual_stream = FALSE;
586 ret = mm_camcorder_get_attributes(handle, &err_name,
587 MMCAM_CAMERA_FPS, &fps,
588 MMCAM_CAMERA_WIDTH, &(info->preview_width),
589 MMCAM_CAMERA_HEIGHT, &(info->preview_height),
590 MMCAM_VIDEO_WIDTH, &(info->video_width),
591 MMCAM_VIDEO_HEIGHT, &(info->video_height),
592 MMCAM_FILE_FORMAT, &fileformat,
593 MMCAM_TARGET_FILENAME, &temp_filename, &size,
594 MMCAM_TARGET_MAX_SIZE, &imax_size,
595 MMCAM_TARGET_TIME_LIMIT, &imax_time,
596 MMCAM_FILE_FORMAT, &(info->fileformat),
597 MMCAM_CAMERA_RECORDING_MOTION_RATE, &motion_rate,
598 MMCAM_ROOT_DIRECTORY, &hcamcorder->root_directory, &root_directory_length,
600 if (ret != MM_ERROR_NONE) {
601 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
603 goto _ERR_CAMCORDER_VIDEO_COMMAND;
606 if (!temp_filename && !hcamcorder->mstream_cb) {
607 _mmcam_dbg_err("filename is not set and muxed stream cb is NULL");
608 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
609 goto _ERR_CAMCORDER_VIDEO_COMMAND;
614 info->max_size = 0; /* do not check */
616 info->max_size = ((guint64)imax_size) << 10; /* to byte */
620 info->max_time = 0; /* do not check */
622 info->max_time = (guint64)((double)imax_time * (double)1000 * motion_rate); /* to millisecond */
624 dir_name = g_path_get_dirname(temp_filename);
626 ret = _mmcamcorder_get_storage_info(dir_name, hcamcorder->root_directory, &hcamcorder->storage_info);
628 _mmcam_dbg_err("get storage info failed");
631 return MM_ERROR_OUT_OF_STORAGE;
634 ret_free_space = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
636 _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "]", dir_name, free_space);
638 if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) {
639 /* MSDOS_SUPER_MAGIC : 0x4d44 */
640 if (file_system_type == MSDOS_SUPER_MAGIC &&
641 (info->max_size == 0 || info->max_size > FAT32_FILE_SYSTEM_MAX_SIZE)) {
642 _mmcam_dbg_warn("FAT32 and too large max[%"G_GUINT64_FORMAT"], set max as %lu",
643 info->max_size, FAT32_FILE_SYSTEM_MAX_SIZE);
644 info->max_size = FAT32_FILE_SYSTEM_MAX_SIZE;
646 _mmcam_dbg_warn("file system 0x%x, max size %"G_GUINT64_FORMAT,
647 file_system_type, info->max_size);
650 _mmcam_dbg_warn("_mmcamcorder_get_file_system_type failed");
656 _mmcam_dbg_err("failed to get directory name");
661 (ret_free_space == -1 || free_space <= _MMCAMCORDER_VIDEO_MINIMUM_SPACE)) {
662 _mmcam_dbg_err("OUT of STORAGE [ret_free_space:%d or free space [%" G_GUINT64_FORMAT "] is smaller than [%d]",
663 ret_free_space, free_space, _MMCAMCORDER_VIDEO_MINIMUM_SPACE);
664 return MM_ERROR_OUT_OF_STORAGE;
667 g_mutex_lock(&hcamcorder->task_thread_lock);
668 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
669 hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
670 /* Play record start sound */
671 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_START, FALSE);
673 g_mutex_unlock(&hcamcorder->task_thread_lock);
675 _mmcam_dbg_warn("video size [%dx%d]", info->video_width, info->video_height);
677 if (info->video_width == 0 || info->video_height == 0) {
678 _mmcam_dbg_warn("video size is invalid [%dx%d] use preview size [%dx%d]",
679 info->video_width, info->video_height, info->preview_width, info->preview_height);
680 info->video_width = info->preview_width;
681 info->video_height = info->preview_height;
684 if (info->support_dual_stream) {
685 _mmcam_dbg_warn("DUAL STREAM MODE");
687 info->record_dual_stream = TRUE;
689 /* No need to restart preview */
690 info->restart_preview = FALSE;
692 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width);
693 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height);
694 } else if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
695 info->preview_width == info->video_width &&
696 info->preview_height == info->video_height) {
697 _mmcam_dbg_log("H264 preview mode and same resolution");
699 /* No need to restart preview */
700 info->restart_preview = FALSE;
702 /* always need to restart preview */
703 info->restart_preview = TRUE;
706 /* set recording hint */
707 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", TRUE);
709 if (info->restart_preview) {
710 /* stop preview and set new size */
711 _mmcam_dbg_log("restart preview");
713 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
714 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
715 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
717 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
719 /* check decoder recreation */
720 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
721 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
722 ret = MM_ERROR_CAMCORDER_INTERNAL;
723 goto _ERR_CAMCORDER_VIDEO_COMMAND;
726 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
727 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
728 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
730 if (ret != MM_ERROR_NONE)
731 goto _ERR_CAMCORDER_VIDEO_COMMAND;
733 if (!_mmcamcorder_set_camera_resolution(handle, info->video_width, info->video_height)) {
734 ret = MM_ERROR_CAMCORDER_INTERNAL;
735 goto _ERR_CAMCORDER_VIDEO_COMMAND;
738 /* Start preview again with new setting */
739 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
740 if (ret != MM_ERROR_NONE)
741 goto _ERR_CAMCORDER_VIDEO_COMMAND;
743 if (motion_rate < 1.0) {
744 _mmcam_dbg_warn("wait for stabilization of frame");
748 _mmcam_dbg_log("no need to restart preview");
751 _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
752 CONFIGURE_CATEGORY_MAIN_RECORD,
756 _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
757 CONFIGURE_CATEGORY_MAIN_RECORD,
758 "PassFirstVideoFrame",
759 &(sc->pass_first_vframe));
761 _mmcam_dbg_log("Drop video frame count[%d], Pass fisrt video frame count[%d]",
762 sc->drop_vframe, sc->pass_first_vframe);
764 info->record_drop_count = (guint)motion_rate;
765 info->record_motion_rate = motion_rate;
766 if (sc->is_modified_rate)
767 info->record_timestamp_ratio = (_MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE/motion_rate);
769 info->record_timestamp_ratio = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
771 _mmcam_dbg_warn("recording fps %d, motion rate %f, timestamp_ratio %f",
772 fps, info->record_motion_rate, info->record_timestamp_ratio);
774 /* set push buffer flag */
775 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT;
776 info->base_video_ts = 0;
778 /* connect video stream cb signal */
779 /*130826 Connect video stream cb for handling fast record frame cb*/
780 if (info->record_dual_stream) {
781 if (_mmcamcorder_connect_video_stream_cb_signal((MMHandleType)hcamcorder) != MM_ERROR_NONE)
782 goto _ERR_CAMCORDER_VIDEO_COMMAND;
785 /* start video stream */
786 if (info->record_dual_stream) {
787 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
789 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
791 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_START");
792 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_START);
794 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
796 _mmcam_dbg_err("could not get camera control");
800 /* check pre-created encode pipeline */
801 g_mutex_lock(&hcamcorder->task_thread_lock);
802 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
803 hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
804 /* create encoding pipeline */
805 ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
806 if (ret != MM_ERROR_NONE) {
807 g_mutex_unlock(&hcamcorder->task_thread_lock);
808 goto _ERR_CAMCORDER_VIDEO_COMMAND;
811 g_mutex_unlock(&hcamcorder->task_thread_lock);
813 /* check recording start sound */
814 _mmcamcorder_sound_solo_play_wait(handle);
816 /**< To fix video recording hanging
817 1. use gst_element_set_start_time() instead of gst_pipeline_set_new_stream_time()
818 2. Set (GstClockTime)1 instead of (GstClockTime)0. Because of strict check in gstreamer 0.25,
819 basetime wouldn't change if you set (GstClockTime)0.
820 3. Move set start time position below PAUSED of pipeline.
823 gst_element_set_start_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), (GstClockTime)1);
824 gst_element_set_start_time(GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), (GstClockTime)1);
827 info->video_frame_count = 0;
828 info->is_firstframe = TRUE;
829 info->audio_frame_count = 0;
831 sc->ferror_send = FALSE;
832 sc->ferror_count = 0;
833 hcamcorder->error_occurs = FALSE;
834 sc->bget_eos = FALSE;
835 sc->muxed_stream_offset = 0;
837 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
838 if (ret != MM_ERROR_NONE) {
839 /* stop video stream */
840 if (info->record_dual_stream) {
841 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
843 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
845 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
846 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
848 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
850 _mmcam_dbg_err("failed to get camera control");
854 /* Remove recorder pipeline and recording file which size maybe zero */
855 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
856 if (info->filename) {
857 _mmcam_dbg_log("file delete(%s)", info->filename);
858 unlink(info->filename);
860 goto _ERR_CAMCORDER_VIDEO_COMMAND;
863 /*set the camera control to create the GOP so that video record will get a new key frame*/
864 if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
865 GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
866 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
867 controls = gst_camera_control_list_channels(CameraControl);
868 if (controls != NULL) {
869 for (item = controls ; item && item->data ; item = item->next) {
870 CameraControlChannel = item->data;
871 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
872 if (!strcmp(CameraControlChannel->label, "new-gop")) {
873 /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
879 _mmcam_dbg_warn("failed to find new-gop control channel");
882 _mmcam_dbg_warn("Can't cast Video source into camera control or not H264 prevew format[%d]",
883 sc->info_image->preview_format);
888 if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
889 GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
890 /* generate and I-frame on resuming */
891 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
892 controls = gst_camera_control_list_channels(CameraControl);
893 if (controls != NULL) {
894 for (item = controls ; item && item->data ; item = item->next) {
895 CameraControlChannel = item->data;
896 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
897 if (!strcmp(CameraControlChannel->label, "new-gop")) {
898 /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
904 _mmcam_dbg_warn("failed to find new-gop control channel");
908 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
910 _mmcam_dbg_log("Object property settings done");
914 case _MMCamcorder_CMD_PAUSE:
916 if (info->b_commiting) {
917 _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
918 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
921 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
922 if (sc->audio_disable) {
923 /* check only video frame */
924 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
926 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
927 _mmcam_dbg_err("Pause fail, frame count %llu", info->video_frame_count);
928 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
930 _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %llu", count, info->video_frame_count);
933 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
935 /* check both of video and audio frame */
936 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
938 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
939 _mmcam_dbg_err("Pause fail, frame count VIDEO[%llu], AUDIO [%llu]",
940 info->video_frame_count, info->audio_frame_count);
941 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
943 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu]",
944 count, info->video_frame_count, info->audio_frame_count);
947 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
951 /* block encodebin */
952 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
955 case _MMCamcorder_CMD_CANCEL:
957 if (info->b_commiting) {
958 _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
959 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
962 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
964 if (hcamcorder->capture_in_recording == FALSE) {
966 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
967 _mmcam_dbg_err("Failed to Wait capture data");
968 hcamcorder->capture_in_recording = FALSE;
971 _mmcam_dbg_warn("Waiting for capture data - retrial [%d]", count);
974 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
977 /* block push buffer */
978 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
980 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
981 if (ret != MM_ERROR_NONE)
982 goto _ERR_CAMCORDER_VIDEO_COMMAND;
984 /* set recording hint */
985 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
987 /* stop video stream */
988 if (info->record_dual_stream) {
989 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
991 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
993 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
994 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
996 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
998 _mmcam_dbg_err("failed to get camera control");
1002 if (info->restart_preview) {
1003 /* restart preview */
1004 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1005 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1006 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1008 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
1010 /* check decoder recreation */
1011 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1012 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1013 ret = MM_ERROR_CAMCORDER_INTERNAL;
1016 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1017 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1018 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1020 if (ret != MM_ERROR_NONE)
1021 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1023 /* reset restart_preview for inset window layout */
1024 info->restart_preview = FALSE;
1026 if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1027 ret = MM_ERROR_CAMCORDER_INTERNAL;
1028 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1031 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
1032 if (ret != MM_ERROR_NONE)
1033 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1036 /* remove target file */
1037 if (info->filename) {
1038 _mmcam_dbg_log("file delete(%s)", info->filename);
1039 unlink(info->filename);
1042 sc->isMaxsizePausing = FALSE;
1043 sc->isMaxtimePausing = FALSE;
1045 sc->display_interval = 0;
1046 sc->previous_slot_time = 0;
1047 info->video_frame_count = 0;
1048 info->audio_frame_count = 0;
1050 hcamcorder->capture_in_recording = FALSE;
1053 case _MMCamcorder_CMD_COMMIT:
1057 if (info->b_commiting) {
1058 _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command);
1059 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
1061 _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
1062 info->b_commiting = TRUE;
1063 sc->bget_eos = FALSE;
1066 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
1067 if (sc->audio_disable) {
1068 /* check only video frame */
1069 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1070 hcamcorder->capture_in_recording == FALSE) {
1072 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1073 _mmcam_dbg_err("Commit fail, frame count is %llu, capturing %d",
1074 info->video_frame_count, hcamcorder->capture_in_recording);
1076 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
1077 _mmcam_dbg_warn("video frames are enough. keep going...");
1079 info->b_commiting = FALSE;
1080 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1083 _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %llu, capturing %d",
1084 count, info->video_frame_count, hcamcorder->capture_in_recording);
1087 /* check both of video and audio frame */
1088 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1089 info->audio_frame_count &&
1090 hcamcorder->capture_in_recording == FALSE) {
1092 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1093 _mmcam_dbg_err("Commit fail, VIDEO[%llu], AUDIO [%llu], capturing %d",
1094 info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1096 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
1097 _mmcam_dbg_warn("video/audio frames are enough. keep going...");
1099 info->b_commiting = FALSE;
1100 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1103 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1105 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu], capturing %d",
1106 count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1110 if (hcamcorder->capture_in_recording) {
1111 gint64 end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND);
1112 if (!_MMCAMCORDER_CMD_WAIT_UNTIL(handle, end_time))
1113 _mmcam_dbg_warn("timeout");
1115 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
1119 /* block push buffer */
1120 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1121 _mmcam_dbg_log("block push buffer to appsrc");
1123 _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1124 if (free_space < _MMCAMCORDER_MINIMUM_SPACE) {
1125 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT out of storage [%" G_GUINT64_FORMAT "]", free_space);
1126 ret = MM_ERROR_OUT_OF_STORAGE;
1127 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1130 if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
1131 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
1132 _mmcam_dbg_warn("VIDEO: send eos to appsrc done");
1134 _mmcam_dbg_err("VIDEO: send EOS failed");
1135 info->b_commiting = FALSE;
1136 ret = MM_ERROR_CAMCORDER_INTERNAL;
1137 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1140 _mmcam_dbg_err("No video stream source");
1141 info->b_commiting = FALSE;
1142 ret = MM_ERROR_CAMCORDER_INTERNAL;
1143 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1146 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
1147 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
1148 _mmcam_dbg_warn("AUDIO: send eos to audiosrc done");
1150 _mmcam_dbg_err("AUDIO: send EOS failed");
1151 info->b_commiting = FALSE;
1152 ret = MM_ERROR_CAMCORDER_INTERNAL;
1153 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1156 _mmcam_dbg_log("No audio stream");
1160 sc->display_interval = 0;
1161 sc->previous_slot_time = 0;
1164 _mmcam_dbg_log("Start to wait EOS");
1165 ret = _mmcamcorder_get_eos_message(handle);
1166 if (ret != MM_ERROR_NONE) {
1167 info->b_commiting = FALSE;
1168 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1172 hcamcorder->capture_in_recording = FALSE;
1176 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1177 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1180 return MM_ERROR_NONE;
1182 _ERR_CAMCORDER_VIDEO_COMMAND:
1183 if (command == _MMCamcorder_CMD_RECORD)
1184 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1190 int _mmcamcorder_video_handle_eos(MMHandleType handle)
1192 int ret = MM_ERROR_NONE;
1194 guint64 file_size = 0;
1196 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1197 _MMCamcorderSubContext *sc = NULL;
1198 _MMCamcorderVideoInfo *info = NULL;
1199 _MMCamcorderMsgItem msg;
1200 MMCamRecordingReport *report = NULL;
1202 mmf_return_val_if_fail(hcamcorder, FALSE);
1204 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1205 mmf_return_val_if_fail(sc, FALSE);
1206 mmf_return_val_if_fail(sc->info_video, FALSE);
1208 info = sc->info_video;
1212 /* Play record stop sound */
1213 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1215 /* remove blocking part */
1216 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1218 mm_camcorder_get_attributes(handle, NULL,
1219 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1222 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1223 if (ret != MM_ERROR_NONE)
1224 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1226 /* set recording hint */
1227 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1229 /* stop video stream */
1230 if (info->record_dual_stream) {
1231 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1233 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1235 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1236 gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1238 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1240 _mmcam_dbg_err("failed to get camera control");
1244 if (enabletag && !(sc->ferror_send)) {
1245 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1246 _mmcam_dbg_log("Writing location information [%s] !!", ret ? "SUCCEEDED" : "FAILED");
1249 /* Check file size */
1250 if (info->max_size > 0) {
1251 _mmcamcorder_get_file_size(info->filename, &file_size);
1252 _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
1253 info->max_size, file_size);
1255 if (file_size > info->max_size) {
1256 _MMCamcorderMsgItem message;
1257 _mmcam_dbg_err("File size is greater than max size !!");
1258 message.id = MM_MESSAGE_CAMCORDER_ERROR;
1259 message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1260 _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1264 if (info->restart_preview) {
1266 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1267 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1268 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1270 _mmcam_dbg_log("Set state of pipeline as READY");
1271 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1273 /* check decoder recreation */
1274 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1275 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1276 ret = MM_ERROR_CAMCORDER_INTERNAL;
1280 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1281 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1282 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1284 if (ret != MM_ERROR_NONE) {
1285 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1286 msg.param.code = ret;
1287 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1288 _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1291 /* reset restart_preview for inset window layout */
1292 info->restart_preview = FALSE;
1294 /* recover preview size */
1295 if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1296 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1297 msg.param.code = MM_ERROR_CAMCORDER_INTERNAL;
1298 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1299 _mmcam_dbg_err("Failed to set camera resolution %dx%d",
1300 info->preview_width, info->preview_height);
1303 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1304 /* Do not return when error is occurred.
1305 Recording file was created successfully, but starting pipeline failed */
1306 if (ret != MM_ERROR_NONE) {
1307 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1308 msg.param.code = ret;
1309 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1310 _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1313 _mmcam_dbg_log("No need to restart preview");
1316 /* Send recording report to application */
1317 msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1318 report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1320 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1322 report->recording_filename = g_strdup(info->filename);
1323 msg.param.data = report;
1325 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1329 sc->pipeline_time = 0;
1331 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1332 sc->isMaxtimePausing = FALSE;
1333 hcamcorder->error_occurs = FALSE;
1335 info->video_frame_count = 0;
1336 info->audio_frame_count = 0;
1338 info->b_commiting = FALSE;
1340 /* check recording stop sound */
1341 _mmcamcorder_sound_solo_play_wait(handle);
1343 _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1349 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1351 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1352 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1354 _MMCamcorderSubContext *sc = NULL;
1355 _MMCamcorderVideoInfo *videoinfo = NULL;
1356 _MMCamcorderMsgItem msg;
1357 guint64 buffer_size = 0;
1358 guint64 trailer_size = 0;
1359 guint64 max_size = 0;
1361 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1362 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1363 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1365 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1366 videoinfo = sc->info_video;
1368 /* get buffer size */
1369 if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1370 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1371 return GST_PAD_PROBE_OK;
1374 buffer_size = mapinfo.size;
1375 gst_buffer_unmap(buffer, &mapinfo);
1377 /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1379 g_mutex_lock(&videoinfo->size_check_lock);
1381 if (videoinfo->audio_frame_count == 0) {
1382 videoinfo->filesize += buffer_size;
1383 videoinfo->audio_frame_count++;
1384 g_mutex_unlock(&videoinfo->size_check_lock);
1385 return GST_PAD_PROBE_OK;
1388 if (sc->ferror_send || sc->isMaxsizePausing) {
1389 _mmcam_dbg_warn("Recording is paused, drop frames");
1390 g_mutex_unlock(&videoinfo->size_check_lock);
1391 return GST_PAD_PROBE_DROP;
1394 /* get trailer size */
1395 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1396 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1400 /* check max size of recorded file */
1401 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1402 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1403 GstState pipeline_state = GST_STATE_VOID_PENDING;
1404 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1405 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1406 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1407 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1408 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1410 if (!sc->isMaxsizePausing) {
1411 sc->isMaxsizePausing = TRUE;
1412 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1413 if (pipeline_state == GST_STATE_PLAYING)
1414 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1416 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1417 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1420 g_mutex_unlock(&videoinfo->size_check_lock);
1425 videoinfo->filesize += buffer_size;
1426 videoinfo->audio_frame_count++;
1428 g_mutex_unlock(&videoinfo->size_check_lock);
1430 return GST_PAD_PROBE_OK;
1434 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1439 guint64 free_space = 0;
1440 guint64 buffer_size = 0;
1441 guint64 trailer_size = 0;
1442 guint64 queued_buffer = 0;
1443 guint64 max_size = 0;
1444 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1446 storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1448 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1449 _MMCamcorderMsgItem msg;
1450 _MMCamcorderSubContext *sc = NULL;
1451 _MMCamcorderVideoInfo *videoinfo = NULL;
1453 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1454 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1456 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1457 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1458 videoinfo = sc->info_video;
1460 /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1461 if (sc->ferror_send) {
1462 _mmcam_dbg_warn("file write error, drop frames");
1463 return GST_PAD_PROBE_DROP;
1466 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1467 buffer_size = mapinfo.size;
1468 gst_buffer_unmap(buffer, &mapinfo);
1470 videoinfo->video_frame_count++;
1471 if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1472 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1473 info->video_frame_count); */
1474 g_mutex_lock(&videoinfo->size_check_lock);
1475 videoinfo->filesize += buffer_size;
1476 g_mutex_unlock(&videoinfo->size_check_lock);
1477 return GST_PAD_PROBE_OK;
1480 /* get trailer size */
1481 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1482 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1486 /* check free space */
1487 ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1489 _mmcam_dbg_err("Error occured. [%d]", ret);
1490 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1491 sc->ferror_send = TRUE;
1493 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1494 msg.param.code = MM_ERROR_FILE_READ;
1496 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1501 return GST_PAD_PROBE_DROP; /* skip this buffer */
1504 if (free_space == 0) {
1505 /* check storage state */
1506 storage_get_state(hcamcorder->storage_info.id, &storage_state);
1508 _mmcam_dbg_warn("storage state %d", storage_state);
1510 if (storage_state == STORAGE_STATE_REMOVED ||
1511 storage_state == STORAGE_STATE_UNMOUNTABLE) {
1512 _mmcam_dbg_err("storage was removed!");
1514 _MMCAMCORDER_LOCK(hcamcorder);
1516 if (sc->ferror_send == FALSE) {
1517 _mmcam_dbg_err("OUT_OF_STORAGE error");
1519 sc->ferror_send = TRUE;
1521 _MMCAMCORDER_UNLOCK(hcamcorder);
1523 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1524 msg.param.code = MM_ERROR_OUT_OF_STORAGE;
1526 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1528 _MMCAMCORDER_UNLOCK(hcamcorder);
1529 _mmcam_dbg_warn("error was already sent");
1532 return GST_PAD_PROBE_DROP;
1536 /* get queued buffer size */
1537 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst)
1538 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
1540 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst)
1541 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1543 queued_buffer = aq_size + vq_size;
1545 if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1546 _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
1547 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
1548 " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
1549 free_space, trailer_size, buffer_size, queued_buffer);
1551 if (!sc->isMaxsizePausing) {
1552 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1553 sc->isMaxsizePausing = TRUE;
1555 msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
1556 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1559 return GST_PAD_PROBE_DROP;
1562 g_mutex_lock(&videoinfo->size_check_lock);
1564 /* check max size of recorded file */
1565 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1566 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1567 GstState pipeline_state = GST_STATE_VOID_PENDING;
1568 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1569 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1570 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1571 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1572 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1574 if (!sc->isMaxsizePausing) {
1575 sc->isMaxsizePausing = TRUE;
1576 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1577 if (pipeline_state == GST_STATE_PLAYING)
1578 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1580 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1581 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1584 g_mutex_unlock(&videoinfo->size_check_lock);
1586 return GST_PAD_PROBE_DROP;
1589 videoinfo->filesize += (guint64)buffer_size;
1592 _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
1595 g_mutex_unlock(&videoinfo->size_check_lock);
1597 return GST_PAD_PROBE_OK;
1601 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1603 guint64 trailer_size = 0;
1604 guint64 rec_pipe_time = 0;
1605 unsigned int remained_time = 0;
1607 GstClockTime b_time;
1609 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1610 _MMCamcorderMsgItem msg;
1611 _MMCamcorderSubContext *sc = NULL;
1612 _MMCamcorderVideoInfo *videoinfo = NULL;
1614 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1616 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1617 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1619 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1620 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1621 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1623 videoinfo = sc->info_video;
1625 b_time = GST_BUFFER_PTS(buffer);
1627 rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1629 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1630 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1634 /* check max time */
1635 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1636 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1637 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1639 if (!sc->isMaxtimePausing) {
1640 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1642 sc->isMaxtimePausing = TRUE;
1644 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1645 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1646 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1647 msg.param.recording_status.remained_time = 0;
1648 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1650 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1651 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1654 return GST_PAD_PROBE_DROP;
1657 /* calculate remained time can be recorded */
1658 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1659 remained_time = videoinfo->max_time - rec_pipe_time;
1660 } else if (videoinfo->max_size > 0) {
1661 long double max_size = (long double)videoinfo->max_size;
1662 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1664 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1667 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1668 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1669 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1670 msg.param.recording_status.remained_time = remained_time;
1671 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1674 _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1675 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1678 if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1679 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1682 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1683 record_motion_rate, videoinfo->record_drop_count);
1686 /* drop some frame if fast motion */
1687 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1688 if (record_motion_rate != (videoinfo->record_drop_count++)) {
1690 _mmcam_dbg_warn("drop frame");
1692 return GST_PAD_PROBE_DROP;
1695 videoinfo->record_drop_count = 1;
1697 _mmcam_dbg_warn("pass frame");
1701 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1702 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1705 return GST_PAD_PROBE_OK;
1709 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1711 _MMCamcorderMsgItem msg;
1712 guint64 trailer_size = 0;
1713 guint64 rec_pipe_time = 0;
1714 _MMCamcorderSubContext *sc = NULL;
1715 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1716 _MMCamcorderVideoInfo *videoinfo = NULL;
1717 unsigned int remained_time = 0;
1718 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1720 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1721 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1722 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1724 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1725 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1726 mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1728 videoinfo = sc->info_video;
1730 if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1731 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1732 return GST_PAD_PROBE_OK;
1735 rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1737 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1738 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1742 /* calculate remained time can be recorded */
1743 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1744 remained_time = videoinfo->max_time - rec_pipe_time;
1745 } else if (videoinfo->max_size > 0) {
1746 long double max_size = (long double)videoinfo->max_size;
1747 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1749 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1752 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1753 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1754 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1756 if (!sc->isMaxtimePausing) {
1757 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1759 sc->isMaxtimePausing = TRUE;
1761 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1762 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1763 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1764 msg.param.recording_status.remained_time = 0;
1765 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1767 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1768 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1771 return GST_PAD_PROBE_DROP;
1774 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1775 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1776 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1777 msg.param.recording_status.remained_time = remained_time;
1778 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1781 _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1782 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1785 return GST_PAD_PROBE_OK;
1789 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1791 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1792 double volume = 0.0;
1795 int err = MM_ERROR_UNKNOWN;
1796 char *err_name = NULL;
1797 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1800 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1801 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1803 /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1804 err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1805 MMCAM_AUDIO_VOLUME, &volume,
1806 MMCAM_AUDIO_FORMAT, &format,
1807 MMCAM_AUDIO_CHANNEL, &channel,
1809 if (err != MM_ERROR_NONE) {
1810 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1811 SAFE_FREE(err_name);
1815 memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1817 gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1819 /* Set audio stream NULL */
1821 memset(mapinfo.data, 0, mapinfo.size);
1823 /* CALL audio stream callback */
1824 if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1825 MMCamcorderAudioStreamDataType stream;
1827 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1828 _mmcam_dbg_warn("Not ready for stream callback");
1829 gst_buffer_unmap(buffer, &mapinfo);
1830 return GST_PAD_PROBE_OK;
1833 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1834 GST_BUFFER_DATA(buffer), width, height, format);*/
1836 stream.data = (void *)mapinfo.data;
1837 stream.format = format;
1838 stream.channel = channel;
1839 stream.length = mapinfo.size;
1840 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1842 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1844 if (hcamcorder->astream_cb)
1845 hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1847 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1850 gst_buffer_unmap(buffer, &mapinfo);
1851 return GST_PAD_PROBE_OK;
1855 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1857 gboolean bret = FALSE;
1859 switch (fileformat) {
1860 case MM_FILE_FORMAT_3GP:
1861 case MM_FILE_FORMAT_MP4:
1862 bret = __mmcamcorder_add_metadata_mp4(handle);
1865 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1873 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1877 guint64 udta_size = 0;
1878 gint64 current_pos = 0;
1879 gint64 moov_pos = 0;
1880 gint64 udta_pos = 0;
1881 gdouble longitude = 0;
1882 gdouble latitude = 0;
1883 gdouble altitude = 0;
1885 int orientation = 0;
1887 char *err_name = NULL;
1888 char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1889 _MMCamcorderLocationInfo location_info = {0, 0, 0};
1890 _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1892 _MMCamcorderVideoInfo *info = NULL;
1893 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1894 _MMCamcorderSubContext *sc = NULL;
1896 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1897 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1899 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1900 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1904 info = sc->info_video;
1906 f = fopen64(info->filename, "rb+");
1908 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1909 _mmcam_dbg_err("file open failed [%s]", err_msg);
1913 mm_camcorder_get_attributes(handle, &err_name,
1914 MMCAM_TAG_LATITUDE, &latitude,
1915 MMCAM_TAG_LONGITUDE, &longitude,
1916 MMCAM_TAG_ALTITUDE, &altitude,
1917 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1918 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1921 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1922 SAFE_FREE(err_name);
1925 location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1926 location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1927 location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1928 geo_info.longitude = longitude *10000;
1929 geo_info.latitude = latitude *10000;
1930 geo_info.altitude = altitude *10000;
1931 /* find udta container.
1932 if, there are udta container, write loci box after that
1933 else, make udta container and write loci box. */
1934 if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1937 _mmcam_dbg_log("find udta container");
1940 if (fseek(f, -8L, SEEK_CUR) != 0)
1943 udta_pos = ftello(f);
1947 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1949 _mmcam_dbg_log("recorded file fread %d", nread);
1951 udta_size = _mmcamcorder_get_container_size(buf);
1953 /* goto end of udta and write 'loci' box */
1954 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1958 if (!_mmcamcorder_write_loci(f, location_info)) {
1959 _mmcam_dbg_err("failed to write loci");
1963 if (!_mmcamcorder_write_geodata(f, geo_info)) {
1964 _mmcam_dbg_err("failed to write geodata");
1969 current_pos = ftello(f);
1970 if (current_pos < 0)
1973 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
1976 _mmcam_dbg_log("No udta container");
1977 if (fseek(f, 0, SEEK_END) != 0)
1980 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
1981 _mmcam_dbg_err("failed to write udta");
1986 /* find moov container.
1987 update moov container size. */
1988 if ((current_pos = ftello(f)) < 0)
1991 if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
1992 gint64 internal_pos = ftello(f);
1994 _mmcam_dbg_log("found moov container");
1995 if (fseek(f, -8L, SEEK_CUR) != 0)
1998 moov_pos = ftello(f);
2002 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
2005 /* add orientation info */
2006 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
2007 _mmcam_dbg_err("fseeko failed : errno %d", errno);
2011 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
2012 _mmcam_dbg_err("failed to find [trak] tag");
2016 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
2017 _mmcam_dbg_err("failed to find [tkhd] tag");
2021 _mmcam_dbg_log("found [tkhd] tag");
2023 /* seek to start position of composition matrix */
2024 if (fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR) == 0) {
2025 /* update composition matrix for orientation */
2026 _mmcamcorder_update_composition_matrix(f, orientation);
2028 _mmcam_dbg_err("fseek failed : errno %d", errno);
2032 _mmcam_dbg_err("No 'moov' container");
2044 _mmcam_dbg_err("ftell() returns negative value.");
2050 int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
2052 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2053 _MMCamcorderSubContext *sc = NULL;
2055 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2057 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2058 mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2060 /* check video source element */
2061 if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
2062 _mmcam_dbg_warn("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
2063 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
2064 _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
2065 G_CALLBACK(__mmcamcorder_video_stream_cb),
2067 return MM_ERROR_NONE;
2069 _mmcam_dbg_err("videosrc element is not created yet");
2070 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
2075 int _mmcamcorder_video_prepare_record(MMHandleType handle)
2077 int ret = MM_ERROR_NONE;
2079 char *temp_filename = NULL;
2081 _MMCamcorderVideoInfo *info = NULL;
2082 _MMCamcorderSubContext *sc = NULL;
2083 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2085 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2087 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2088 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2089 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2091 info = sc->info_video;
2093 _mmcam_dbg_warn("start");
2095 /* create encoding pipeline */
2096 ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2097 if (ret != MM_ERROR_NONE)
2098 goto _ERR_PREPARE_RECORD;
2100 SAFE_G_FREE(info->filename);
2102 mm_camcorder_get_attributes(handle, NULL,
2103 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2105 if (temp_filename) {
2106 info->filename = g_strdup(temp_filename);
2107 if (!info->filename) {
2108 _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
2109 goto _ERR_PREPARE_RECORD;
2112 _mmcam_dbg_log("Record file name [%s]", info->filename);
2113 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2115 _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
2116 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
2119 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2121 /* Adjust display FPS */
2122 sc->display_interval = 0;
2123 sc->previous_slot_time = 0;
2125 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2126 if (ret != MM_ERROR_NONE)
2127 goto _ERR_PREPARE_RECORD;
2129 _mmcam_dbg_warn("done");
2133 _ERR_PREPARE_RECORD:
2134 /* Remove recorder pipeline and recording file which size maybe zero */
2135 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2136 if (info && info->filename) {
2137 _mmcam_dbg_log("file delete(%s)", info->filename);
2138 unlink(info->filename);