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 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1213 /* Play record stop sound */
1214 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1216 _mmcam_dbg_warn("Play stop sound through pulseaudio");
1218 _mmcamcorder_sound_init(handle);
1220 _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, TRUE);
1222 _mmcamcorder_sound_finalize(handle);
1225 /* remove blocking part */
1226 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1228 mm_camcorder_get_attributes(handle, NULL,
1229 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1232 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1233 if (ret != MM_ERROR_NONE)
1234 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1236 /* set recording hint */
1237 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1239 /* stop video stream */
1240 if (info->record_dual_stream) {
1241 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1243 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1245 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1246 gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1248 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1250 _mmcam_dbg_err("failed to get camera control");
1254 if (enabletag && !(sc->ferror_send)) {
1255 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1256 _mmcam_dbg_log("Writing location information [%s] !!", ret ? "SUCCEEDED" : "FAILED");
1259 /* Check file size */
1260 if (info->max_size > 0) {
1261 _mmcamcorder_get_file_size(info->filename, &file_size);
1262 _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
1263 info->max_size, file_size);
1265 if (file_size > info->max_size) {
1266 _MMCamcorderMsgItem message;
1267 _mmcam_dbg_err("File size is greater than max size !!");
1268 message.id = MM_MESSAGE_CAMCORDER_ERROR;
1269 message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1270 _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1274 if (info->restart_preview) {
1276 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1277 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1278 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1280 _mmcam_dbg_log("Set state of pipeline as READY");
1281 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1283 /* check decoder recreation */
1284 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1285 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1286 ret = MM_ERROR_CAMCORDER_INTERNAL;
1290 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1291 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1292 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1294 if (ret != MM_ERROR_NONE) {
1295 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1296 msg.param.code = ret;
1297 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1298 _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1301 /* reset restart_preview for inset window layout */
1302 info->restart_preview = FALSE;
1304 /* recover preview size */
1305 if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1306 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1307 msg.param.code = MM_ERROR_CAMCORDER_INTERNAL;
1308 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1309 _mmcam_dbg_err("Failed to set camera resolution %dx%d",
1310 info->preview_width, info->preview_height);
1313 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1314 /* Do not return when error is occurred.
1315 Recording file was created successfully, but starting pipeline failed */
1316 if (ret != MM_ERROR_NONE) {
1317 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1318 msg.param.code = ret;
1319 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1320 _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1323 _mmcam_dbg_log("No need to restart preview");
1326 /* Send recording report to application */
1327 msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1328 report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1330 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1332 report->recording_filename = g_strdup(info->filename);
1333 msg.param.data = report;
1335 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1339 sc->pipeline_time = 0;
1341 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1342 sc->isMaxtimePausing = FALSE;
1343 hcamcorder->error_occurs = FALSE;
1345 info->video_frame_count = 0;
1346 info->audio_frame_count = 0;
1348 info->b_commiting = FALSE;
1350 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1351 /* check recording stop sound */
1352 _mmcamcorder_sound_solo_play_wait(handle);
1355 _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1361 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1363 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1364 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1366 _MMCamcorderSubContext *sc = NULL;
1367 _MMCamcorderVideoInfo *videoinfo = NULL;
1368 _MMCamcorderMsgItem msg;
1369 guint64 buffer_size = 0;
1370 guint64 trailer_size = 0;
1371 guint64 max_size = 0;
1373 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1374 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1375 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1377 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1378 videoinfo = sc->info_video;
1380 /* get buffer size */
1381 if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1382 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1383 return GST_PAD_PROBE_OK;
1386 buffer_size = mapinfo.size;
1387 gst_buffer_unmap(buffer, &mapinfo);
1389 /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1391 g_mutex_lock(&videoinfo->size_check_lock);
1393 if (videoinfo->audio_frame_count == 0) {
1394 videoinfo->filesize += buffer_size;
1395 videoinfo->audio_frame_count++;
1396 g_mutex_unlock(&videoinfo->size_check_lock);
1397 return GST_PAD_PROBE_OK;
1400 if (sc->ferror_send || sc->isMaxsizePausing) {
1401 _mmcam_dbg_warn("Recording is paused, drop frames");
1402 g_mutex_unlock(&videoinfo->size_check_lock);
1403 return GST_PAD_PROBE_DROP;
1406 /* get trailer size */
1407 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1408 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1412 /* check max size of recorded file */
1413 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1414 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1415 GstState pipeline_state = GST_STATE_VOID_PENDING;
1416 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1417 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1418 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1419 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1420 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1422 if (!sc->isMaxsizePausing) {
1423 sc->isMaxsizePausing = TRUE;
1424 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1425 if (pipeline_state == GST_STATE_PLAYING)
1426 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1428 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1429 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1432 g_mutex_unlock(&videoinfo->size_check_lock);
1437 videoinfo->filesize += buffer_size;
1438 videoinfo->audio_frame_count++;
1440 g_mutex_unlock(&videoinfo->size_check_lock);
1442 return GST_PAD_PROBE_OK;
1446 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1451 guint64 free_space = 0;
1452 guint64 buffer_size = 0;
1453 guint64 trailer_size = 0;
1454 guint64 queued_buffer = 0;
1455 guint64 max_size = 0;
1456 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1458 storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1460 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1461 _MMCamcorderMsgItem msg;
1462 _MMCamcorderSubContext *sc = NULL;
1463 _MMCamcorderVideoInfo *videoinfo = NULL;
1465 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1466 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1468 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1469 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1470 videoinfo = sc->info_video;
1472 /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1473 if (sc->ferror_send) {
1474 _mmcam_dbg_warn("file write error, drop frames");
1475 return GST_PAD_PROBE_DROP;
1478 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1479 buffer_size = mapinfo.size;
1480 gst_buffer_unmap(buffer, &mapinfo);
1482 videoinfo->video_frame_count++;
1483 if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1484 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1485 info->video_frame_count); */
1486 g_mutex_lock(&videoinfo->size_check_lock);
1487 videoinfo->filesize += buffer_size;
1488 g_mutex_unlock(&videoinfo->size_check_lock);
1489 return GST_PAD_PROBE_OK;
1492 /* get trailer size */
1493 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1494 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1498 /* check free space */
1499 ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1501 _mmcam_dbg_err("Error occured. [%d]", ret);
1502 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1503 sc->ferror_send = TRUE;
1505 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1506 msg.param.code = MM_ERROR_FILE_READ;
1508 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1513 return GST_PAD_PROBE_DROP; /* skip this buffer */
1516 if (free_space == 0) {
1517 /* check storage state */
1518 storage_get_state(hcamcorder->storage_info.id, &storage_state);
1520 _mmcam_dbg_warn("storage state %d", storage_state);
1522 if (storage_state == STORAGE_STATE_REMOVED ||
1523 storage_state == STORAGE_STATE_UNMOUNTABLE) {
1524 _mmcam_dbg_err("storage was removed!");
1526 _MMCAMCORDER_LOCK(hcamcorder);
1528 if (sc->ferror_send == FALSE) {
1529 _mmcam_dbg_err("OUT_OF_STORAGE error");
1531 sc->ferror_send = TRUE;
1533 _MMCAMCORDER_UNLOCK(hcamcorder);
1535 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1536 msg.param.code = MM_ERROR_OUT_OF_STORAGE;
1538 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1540 _MMCAMCORDER_UNLOCK(hcamcorder);
1541 _mmcam_dbg_warn("error was already sent");
1544 return GST_PAD_PROBE_DROP;
1548 /* get queued buffer size */
1549 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst)
1550 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
1552 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst)
1553 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1555 queued_buffer = aq_size + vq_size;
1557 if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1558 _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
1559 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
1560 " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
1561 free_space, trailer_size, buffer_size, queued_buffer);
1563 if (!sc->isMaxsizePausing) {
1564 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1565 sc->isMaxsizePausing = TRUE;
1567 msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
1568 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1571 return GST_PAD_PROBE_DROP;
1574 g_mutex_lock(&videoinfo->size_check_lock);
1576 /* check max size of recorded file */
1577 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1578 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1579 GstState pipeline_state = GST_STATE_VOID_PENDING;
1580 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1581 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1582 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1583 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1584 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1586 if (!sc->isMaxsizePausing) {
1587 sc->isMaxsizePausing = TRUE;
1588 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1589 if (pipeline_state == GST_STATE_PLAYING)
1590 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1592 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1593 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1596 g_mutex_unlock(&videoinfo->size_check_lock);
1598 return GST_PAD_PROBE_DROP;
1601 videoinfo->filesize += (guint64)buffer_size;
1604 _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
1607 g_mutex_unlock(&videoinfo->size_check_lock);
1609 return GST_PAD_PROBE_OK;
1613 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1615 guint64 trailer_size = 0;
1616 guint64 rec_pipe_time = 0;
1617 unsigned int remained_time = 0;
1619 GstClockTime b_time;
1621 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1622 _MMCamcorderMsgItem msg;
1623 _MMCamcorderSubContext *sc = NULL;
1624 _MMCamcorderVideoInfo *videoinfo = NULL;
1626 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1628 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1629 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1631 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1632 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1633 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1635 videoinfo = sc->info_video;
1637 b_time = GST_BUFFER_PTS(buffer);
1639 rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1641 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1642 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1646 /* check max time */
1647 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1648 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1649 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1651 if (!sc->isMaxtimePausing) {
1652 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1654 sc->isMaxtimePausing = TRUE;
1656 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1657 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1658 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1659 msg.param.recording_status.remained_time = 0;
1660 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1662 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1663 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1666 return GST_PAD_PROBE_DROP;
1669 /* calculate remained time can be recorded */
1670 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1671 remained_time = videoinfo->max_time - rec_pipe_time;
1672 } else if (videoinfo->max_size > 0) {
1673 long double max_size = (long double)videoinfo->max_size;
1674 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1676 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1679 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1680 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1681 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1682 msg.param.recording_status.remained_time = remained_time;
1683 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1686 _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1687 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1690 if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1691 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1694 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1695 record_motion_rate, videoinfo->record_drop_count);
1698 /* drop some frame if fast motion */
1699 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1700 if (record_motion_rate != (videoinfo->record_drop_count++)) {
1702 _mmcam_dbg_warn("drop frame");
1704 return GST_PAD_PROBE_DROP;
1707 videoinfo->record_drop_count = 1;
1709 _mmcam_dbg_warn("pass frame");
1713 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1714 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1717 return GST_PAD_PROBE_OK;
1721 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1723 _MMCamcorderMsgItem msg;
1724 guint64 trailer_size = 0;
1725 guint64 rec_pipe_time = 0;
1726 _MMCamcorderSubContext *sc = NULL;
1727 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1728 _MMCamcorderVideoInfo *videoinfo = NULL;
1729 unsigned int remained_time = 0;
1730 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1732 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1733 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1734 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1736 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1737 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1738 mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1740 videoinfo = sc->info_video;
1742 if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1743 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1744 return GST_PAD_PROBE_OK;
1747 rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1749 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1750 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1754 /* calculate remained time can be recorded */
1755 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1756 remained_time = videoinfo->max_time - rec_pipe_time;
1757 } else if (videoinfo->max_size > 0) {
1758 long double max_size = (long double)videoinfo->max_size;
1759 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1761 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1764 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1765 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1766 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1768 if (!sc->isMaxtimePausing) {
1769 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1771 sc->isMaxtimePausing = TRUE;
1773 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1774 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1775 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1776 msg.param.recording_status.remained_time = 0;
1777 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1779 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1780 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1783 return GST_PAD_PROBE_DROP;
1786 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1787 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1788 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1789 msg.param.recording_status.remained_time = remained_time;
1790 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1793 _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1794 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1797 return GST_PAD_PROBE_OK;
1801 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1803 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1804 double volume = 0.0;
1807 int err = MM_ERROR_UNKNOWN;
1808 char *err_name = NULL;
1809 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1812 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1813 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1815 /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1816 err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1817 MMCAM_AUDIO_VOLUME, &volume,
1818 MMCAM_AUDIO_FORMAT, &format,
1819 MMCAM_AUDIO_CHANNEL, &channel,
1821 if (err != MM_ERROR_NONE) {
1822 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1823 SAFE_FREE(err_name);
1827 memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1829 gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1831 /* Set audio stream NULL */
1833 memset(mapinfo.data, 0, mapinfo.size);
1835 /* CALL audio stream callback */
1836 if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1837 MMCamcorderAudioStreamDataType stream;
1839 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1840 _mmcam_dbg_warn("Not ready for stream callback");
1841 gst_buffer_unmap(buffer, &mapinfo);
1842 return GST_PAD_PROBE_OK;
1845 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1846 GST_BUFFER_DATA(buffer), width, height, format);*/
1848 stream.data = (void *)mapinfo.data;
1849 stream.format = format;
1850 stream.channel = channel;
1851 stream.length = mapinfo.size;
1852 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1854 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1856 if (hcamcorder->astream_cb)
1857 hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1859 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1862 gst_buffer_unmap(buffer, &mapinfo);
1863 return GST_PAD_PROBE_OK;
1867 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1869 gboolean bret = FALSE;
1871 switch (fileformat) {
1872 case MM_FILE_FORMAT_3GP:
1873 case MM_FILE_FORMAT_MP4:
1874 bret = __mmcamcorder_add_metadata_mp4(handle);
1877 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1885 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1889 guint64 udta_size = 0;
1890 gint64 current_pos = 0;
1891 gint64 moov_pos = 0;
1892 gint64 udta_pos = 0;
1893 gdouble longitude = 0;
1894 gdouble latitude = 0;
1895 gdouble altitude = 0;
1897 int orientation = 0;
1899 char *err_name = NULL;
1900 char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1901 _MMCamcorderLocationInfo location_info = {0, 0, 0};
1902 _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1904 _MMCamcorderVideoInfo *info = NULL;
1905 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1906 _MMCamcorderSubContext *sc = NULL;
1908 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1909 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1911 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1912 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1916 info = sc->info_video;
1918 f = fopen64(info->filename, "rb+");
1920 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1921 _mmcam_dbg_err("file open failed [%s]", err_msg);
1925 mm_camcorder_get_attributes(handle, &err_name,
1926 MMCAM_TAG_LATITUDE, &latitude,
1927 MMCAM_TAG_LONGITUDE, &longitude,
1928 MMCAM_TAG_ALTITUDE, &altitude,
1929 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1930 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1933 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1934 SAFE_FREE(err_name);
1937 location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1938 location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1939 location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1940 geo_info.longitude = longitude *10000;
1941 geo_info.latitude = latitude *10000;
1942 geo_info.altitude = altitude *10000;
1943 /* find udta container.
1944 if, there are udta container, write loci box after that
1945 else, make udta container and write loci box. */
1946 if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1949 _mmcam_dbg_log("find udta container");
1952 if (fseek(f, -8L, SEEK_CUR) != 0)
1955 udta_pos = ftello(f);
1959 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1961 _mmcam_dbg_log("recorded file fread %d", nread);
1963 udta_size = _mmcamcorder_get_container_size(buf);
1965 /* goto end of udta and write 'loci' box */
1966 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1970 if (!_mmcamcorder_write_loci(f, location_info)) {
1971 _mmcam_dbg_err("failed to write loci");
1975 if (!_mmcamcorder_write_geodata(f, geo_info)) {
1976 _mmcam_dbg_err("failed to write geodata");
1981 current_pos = ftello(f);
1982 if (current_pos < 0)
1985 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
1988 _mmcam_dbg_log("No udta container");
1989 if (fseek(f, 0, SEEK_END) != 0)
1992 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
1993 _mmcam_dbg_err("failed to write udta");
1998 /* find moov container.
1999 update moov container size. */
2000 if ((current_pos = ftello(f)) < 0)
2003 if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
2004 gint64 internal_pos = ftello(f);
2006 _mmcam_dbg_log("found moov container");
2007 if (fseek(f, -8L, SEEK_CUR) != 0)
2010 moov_pos = ftello(f);
2014 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
2017 /* add orientation info */
2018 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
2019 _mmcam_dbg_err("fseeko failed : errno %d", errno);
2023 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
2024 _mmcam_dbg_err("failed to find [trak] tag");
2028 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
2029 _mmcam_dbg_err("failed to find [tkhd] tag");
2033 _mmcam_dbg_log("found [tkhd] tag");
2035 /* seek to start position of composition matrix */
2036 if (fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR) == 0) {
2037 /* update composition matrix for orientation */
2038 _mmcamcorder_update_composition_matrix(f, orientation);
2040 _mmcam_dbg_err("fseek failed : errno %d", errno);
2044 _mmcam_dbg_err("No 'moov' container");
2056 _mmcam_dbg_err("ftell() returns negative value.");
2062 int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
2064 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2065 _MMCamcorderSubContext *sc = NULL;
2067 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2069 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2070 mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2072 /* check video source element */
2073 if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
2074 _mmcam_dbg_warn("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
2075 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
2076 _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
2077 G_CALLBACK(__mmcamcorder_video_stream_cb),
2079 return MM_ERROR_NONE;
2081 _mmcam_dbg_err("videosrc element is not created yet");
2082 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
2087 int _mmcamcorder_video_prepare_record(MMHandleType handle)
2089 int ret = MM_ERROR_NONE;
2091 char *temp_filename = NULL;
2093 _MMCamcorderVideoInfo *info = NULL;
2094 _MMCamcorderSubContext *sc = NULL;
2095 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2097 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2099 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2100 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2101 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2103 info = sc->info_video;
2105 _mmcam_dbg_warn("start");
2107 /* create encoding pipeline */
2108 ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2109 if (ret != MM_ERROR_NONE)
2110 goto _ERR_PREPARE_RECORD;
2112 SAFE_G_FREE(info->filename);
2114 mm_camcorder_get_attributes(handle, NULL,
2115 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2117 if (temp_filename) {
2118 info->filename = g_strdup(temp_filename);
2119 if (!info->filename) {
2120 _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
2121 goto _ERR_PREPARE_RECORD;
2124 _mmcam_dbg_log("Record file name [%s]", info->filename);
2125 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2127 _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
2128 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
2131 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2133 /* Adjust display FPS */
2134 sc->display_interval = 0;
2135 sc->previous_slot_time = 0;
2137 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2138 if (ret != MM_ERROR_NONE)
2139 goto _ERR_PREPARE_RECORD;
2141 _mmcam_dbg_warn("done");
2145 _ERR_PREPARE_RECORD:
2146 /* Remove recorder pipeline and recording file which size maybe zero */
2147 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2148 if (info && info->filename) {
2149 _mmcam_dbg_log("file delete(%s)", info->filename);
2150 unlink(info->filename);