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*/
45 /*---------------------------------------------------------------------------------------
46 | LOCAL FUNCTION PROTOTYPES: |
47 ---------------------------------------------------------------------------------------*/
48 /* STATIC INTERNAL FUNCTION */
49 static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data);
50 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
51 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
52 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
53 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
54 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
55 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat);
56 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle);
58 /*=======================================================================================
59 | FUNCTION DEFINITIONS |
60 =======================================================================================*/
61 /*---------------------------------------------------------------------------------------
62 | GLOBAL FUNCTION DEFINITIONS: |
63 ---------------------------------------------------------------------------------------*/
64 static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
66 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
67 _MMCamcorderSubContext *sc = NULL;
69 GstBuffer *buffer = gst_sample_get_buffer(sample);
70 mmf_return_val_if_fail(buffer, FALSE);
71 mmf_return_val_if_fail(gst_buffer_n_memory(buffer), FALSE);
72 mmf_return_val_if_fail(hcamcorder, FALSE);
74 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
75 mmf_return_val_if_fail(sc, FALSE);
78 _mmcam_dbg_log("ENTER - push_encoding_buffer %d, buffer %p, MALLOCDATA %p, size %d",
79 sc->info_video->push_encoding_buffer, buffer, GST_BUFFER_MALLOCDATA(buffer), GST_BUFFER_SIZE(buffer));
82 /* push buffer in appsrc to encode */
83 if (sc->info_video->push_encoding_buffer == PUSH_ENCODING_BUFFER_RUN &&
84 sc->info_video->record_dual_stream &&
85 sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst) {
86 GstFlowReturn ret = 0;
87 GstClock *pipe_clock = NULL;
89 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst) {
90 if (sc->info_video->is_firstframe) {
91 sc->info_video->is_firstframe = FALSE;
92 pipe_clock = GST_ELEMENT_CLOCK(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst);
94 gst_object_ref(pipe_clock);
95 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);
96 gst_object_unref(pipe_clock);
100 if (sc->info_video->is_firstframe) {
101 sc->info_video->is_firstframe = FALSE;
102 sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer);
106 GST_BUFFER_PTS(buffer) = GST_BUFFER_PTS(buffer) - sc->info_video->base_video_ts;
107 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
109 ret = gst_app_src_push_buffer((GstAppSrc *)sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, buffer);
110 if (ret != GST_FLOW_OK && ret != GST_FLOW_FLUSHING) {
111 _mmcam_dbg_err("gst_app_src_push_buffer failed [0x%x]", ret);
112 gst_buffer_unref(buffer);
116 /*_mmcam_dbg_log("push buffer result : 0x%x", ret);*/
118 _mmcam_dbg_warn("unref video buffer immediately - push encoding buffer %d",
119 sc->info_video->push_encoding_buffer);
121 gst_buffer_unref(buffer);
129 int _mmcamcorder_create_recorder_pipeline(MMHandleType handle)
132 int err = MM_ERROR_NONE;
133 const char* gst_element_rsink_name = NULL;
136 GstPad *srcpad = NULL;
137 GstPad *sinkpad = NULL;
139 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
140 _MMCamcorderSubContext *sc = NULL;
142 type_element *RecordsinkElement = NULL;
144 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
146 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
147 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
148 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
150 _mmcam_dbg_warn("start");
152 err = _mmcamcorder_check_videocodec_fileformat_compatibility(handle);
153 if (err != MM_ERROR_NONE)
157 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
158 _mmcam_dbg_log("pipeline is exist so need to remove pipeline _MMCAMCORDER_ENCODE_MAIN_PIPE = %p",
159 sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
160 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
163 _MMCAMCORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
165 /* get audio disable */
166 mm_camcorder_get_attributes(handle, NULL,
167 MMCAM_AUDIO_DISABLE, &sc->audio_disable,
170 _mmcam_dbg_log("MMCAM_AUDIO_DISABLE %d, is_modified_rate %d",
171 sc->audio_disable, sc->is_modified_rate);
173 sc->audio_disable |= sc->is_modified_rate;
175 if (sc->audio_disable == FALSE) {
176 /* create audiosrc bin */
177 err = _mmcamcorder_create_audiosrc_bin((MMHandleType)hcamcorder);
178 if (err != MM_ERROR_NONE)
182 err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder, MM_CAMCORDER_ENCBIN_PROFILE_VIDEO);
183 if (err != MM_ERROR_NONE)
186 if (sc->audio_disable == FALSE) {
187 gst_bin_add(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
188 sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
191 /* add element and encodesink bin to encode main pipeline */
192 gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
193 sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst,
194 sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst,
195 sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
198 /* Link each element : appsrc - capsfilter - encodesink bin */
199 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "src");
200 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "sink");
201 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
203 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "src");
204 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
205 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
207 if (sc->audio_disable == FALSE) {
208 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
209 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
210 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
213 _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
214 CONFIGURE_CATEGORY_MAIN_RECORD,
217 _mmcamcorder_conf_get_value_element_name(RecordsinkElement, &gst_element_rsink_name);
219 /* set data probe function */
221 /* register message cb */
223 /* set data probe functions */
224 if (sc->audio_disable == FALSE) {
225 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "sink");
226 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
227 __mmcamcorder_audioque_dataprobe, hcamcorder);
228 gst_object_unref(sinkpad);
232 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
233 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
234 __mmcamcorder_audio_dataprobe_audio_mute, hcamcorder);
235 gst_object_unref(srcpad);
238 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
239 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "src");
240 MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
241 __mmcamcorder_eventprobe_monitor, hcamcorder);
242 gst_object_unref(srcpad);
247 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
248 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "src");
249 MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
250 __mmcamcorder_eventprobe_monitor, hcamcorder);
251 gst_object_unref(srcpad);
255 if (sc->audio_disable) {
256 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "sink");
257 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
258 __mmcamcorder_video_dataprobe_audio_disable, hcamcorder);
259 gst_object_unref(sinkpad);
263 if (!strcmp(gst_element_rsink_name, "filesink")) {
264 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
265 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
266 __mmcamcorder_video_dataprobe_record, hcamcorder);
267 gst_object_unref(srcpad);
270 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
271 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
272 __mmcamcorder_audio_dataprobe_check, hcamcorder);
273 gst_object_unref(srcpad);
277 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "sink");
278 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
279 __mmcamcorder_muxed_dataprobe, hcamcorder);
280 MMCAMCORDER_ADD_EVENT_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
281 __mmcamcorder_eventprobe_monitor, hcamcorder);
282 gst_object_unref(sinkpad);
285 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
287 /* register pipeline message callback */
288 hcamcorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder);
290 /* set sync handler */
291 gst_bus_set_sync_handler(bus, _mmcamcorder_encode_pipeline_bus_sync_callback, (gpointer)hcamcorder, NULL);
293 gst_object_unref(bus);
296 return MM_ERROR_NONE;
298 pipeline_creation_error:
299 for (i = _MMCAMCORDER_AUDIOSRC_BIN ; i <= _MMCAMCORDER_ENCSINK_SINK ; i++)
300 _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, i);
302 _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE);
307 int _mmcamcorder_remove_audio_pipeline(MMHandleType handle)
309 GstPad *srcpad = NULL;
310 GstPad *sinkpad = NULL;
311 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
312 _MMCamcorderSubContext *sc = NULL;
314 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
316 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
317 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
318 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
322 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst != NULL) {
323 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
324 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
325 _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
327 /* release audiosrc bin */
328 gst_bin_remove(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
329 sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
332 To avoid conflicting between old elements and newly created elements,
333 I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
334 This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
335 So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
336 It's because the pipeline of audio recording destroys at the same time,
337 and '_mmcamcorder_element_release_noti' will perfom removing handle.
339 _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element, _MMCAMCORDER_AUDIOSRC_BIN, _MMCAMCORDER_AUDIOSRC_VOL);
341 _mmcam_dbg_log("Audio pipeline removed");
344 return MM_ERROR_NONE;
348 int _mmcamcorder_remove_encode_pipeline(MMHandleType handle)
350 GstPad *reqpad = NULL;
351 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
352 _MMCamcorderSubContext *sc = NULL;
353 #ifdef _MMCAMCORDER_MURPHY_SUPPORT
354 int ret = MM_ERROR_NONE;
355 MMCamcorderResourceManager *resource_manager = NULL;
356 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
358 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
360 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
361 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
362 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
366 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst != NULL) {
367 /* release request pad */
368 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
370 gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
371 gst_object_unref(reqpad);
375 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
377 gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
378 gst_object_unref(reqpad);
382 /* release encode main pipeline */
383 gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
386 To avoid conflicting between old elements and newly created elements,
387 I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
388 This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
389 So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
390 It's because the pipeline of audio recording destroys at the same time,
391 and '_mmcamcorder_element_release_noti' will perfom removing handle.
393 /* _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element,
394 _MMCAMCORDER_ENCODE_MAIN_PIPE, _MMCAMCORDER_ENCSINK_SINK); */
396 _mmcam_dbg_warn("Encoder pipeline removed");
398 #ifdef _MMCAMCORDER_MURPHY_SUPPORT
399 resource_manager = &hcamcorder->resource_manager_sub;
401 _mmcam_dbg_warn("lock resource - cb calling %d", resource_manager->is_release_cb_calling);
403 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
405 if (resource_manager->is_release_cb_calling == FALSE) {
406 /* release resource */
407 ret = _mmcamcorder_resource_manager_release(resource_manager);
409 _mmcam_dbg_warn("release resource 0x%x", ret);
411 if (resource_manager->acquire_remain < resource_manager->acquire_count) {
412 /* wait for resource release */
413 gint64 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
414 _mmcam_dbg_log("resource is not released all. wait for signal...");
415 _MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time);
419 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
421 _mmcam_dbg_warn("unlock resource");
422 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
425 return MM_ERROR_NONE;
429 int _mmcamcorder_remove_recorder_pipeline(MMHandleType handle)
431 int ret = MM_ERROR_NONE;
432 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
433 _MMCamcorderSubContext *sc = NULL;
437 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
438 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
439 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
441 _mmcam_dbg_log("start");
443 if (!sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
444 _mmcam_dbg_warn("pipeline is not existed.");
445 return MM_ERROR_NONE;
448 _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_VIDEOREC);
450 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
451 if (ret != MM_ERROR_NONE) {
452 _mmcam_dbg_err("Faile to change encode main pipeline [0x%x]", ret);
456 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
458 /* remove audio pipeline first */
459 ret = _mmcamcorder_remove_audio_pipeline(handle);
460 if (ret != MM_ERROR_NONE) {
461 _mmcam_dbg_err("Fail to remove audio pipeline");
465 ret = _mmcamcorder_remove_encode_pipeline(handle);
466 if (ret != MM_ERROR_NONE) {
467 _mmcam_dbg_err("Fail to remove encoder pipeline");
471 /* Remove pipeline message callback */
472 if (hcamcorder->encode_pipeline_cb_event_id != 0) {
473 g_source_remove(hcamcorder->encode_pipeline_cb_event_id);
474 hcamcorder->encode_pipeline_cb_event_id = 0;
477 /* Remove remained message */
479 GstMessage *gst_msg = NULL;
480 while ((gst_msg = gst_bus_pop(bus)) != NULL) {
481 _mmcamcorder_pipeline_cb_message(bus, gst_msg, (gpointer)hcamcorder);
482 gst_message_unref(gst_msg);
485 gst_object_unref(bus);
489 _mmcam_dbg_log("done");
495 int _mmcamcorder_video_command(MMHandleType handle, int command)
500 int ret = MM_ERROR_NONE;
501 double motion_rate = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
502 char *err_name = NULL;
503 char *temp_filename = NULL;
504 GstCameraControl *CameraControl = NULL;
505 GstCameraControlChannel *CameraControlChannel = NULL;
506 const GList *controls = NULL;
507 const GList *item = NULL;
510 GstElement *pipeline = NULL;
512 _MMCamcorderVideoInfo *info = NULL;
513 _MMCamcorderSubContext *sc = NULL;
514 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
516 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
518 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
519 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
520 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
521 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
523 info = sc->info_video;
525 _mmcam_dbg_log("Command(%d)", command);
527 pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
530 case _MMCamcorder_CMD_RECORD:
532 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED) {
538 int ret_free_space = 0;
539 char *dir_name = NULL;
540 guint64 free_space = 0;
541 int file_system_type = 0;
542 int root_directory_length = 0;
545 _mmcam_dbg_log("Record Start - dual stream %d", info->support_dual_stream);
547 #ifdef _MMCAMCORDER_MURPHY_SUPPORT
548 /* check connection */
549 ret = _mmcamcorder_resource_check_connection(&hcamcorder->resource_manager_sub);
550 if (ret != MM_ERROR_NONE)
551 goto _ERR_CAMCORDER_VIDEO_COMMAND;
553 /* create resource set */
554 ret = _mmcamcorder_resource_create_resource_set(&hcamcorder->resource_manager_sub);
555 if (ret != MM_ERROR_NONE)
556 goto _ERR_CAMCORDER_VIDEO_COMMAND;
558 hcamcorder->resource_manager_sub.acquire_count = 0;
560 /* prepare resource manager for H/W encoder */
561 ret = _mmcamcorder_resource_manager_prepare(&hcamcorder->resource_manager_sub, MM_CAMCORDER_RESOURCE_TYPE_VIDEO_ENCODER);
562 if (ret != MM_ERROR_NONE) {
563 _mmcam_dbg_err("could not prepare for video_encoder resource");
564 ret = MM_ERROR_CAMCORDER_INTERNAL;
565 goto _ERR_CAMCORDER_VIDEO_COMMAND;
568 /* acquire resources */
569 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
571 ret = _mmcamcorder_resource_manager_acquire(&hcamcorder->resource_manager_sub);
572 if (ret != MM_ERROR_NONE) {
573 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
574 _mmcam_dbg_err("could not acquire resource");
575 goto _ERR_CAMCORDER_VIDEO_COMMAND;
578 if (hcamcorder->resource_manager_sub.acquire_remain > 0) {
581 _mmcam_dbg_warn("wait for resource state change");
583 /* wait for resource state change */
584 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
586 if (_MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time)) {
587 _mmcam_dbg_warn("signal received");
589 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
590 _mmcam_dbg_err("timeout");
591 ret = MM_ERROR_RESOURCE_INTERNAL;
592 goto _ERR_CAMCORDER_VIDEO_COMMAND;
595 _mmcam_dbg_log("already acquired");
598 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
599 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
601 /* init record_dual_stream */
602 info->record_dual_stream = FALSE;
604 ret = mm_camcorder_get_attributes(handle, &err_name,
605 MMCAM_CAMERA_FPS, &fps,
606 MMCAM_CAMERA_WIDTH, &(info->preview_width),
607 MMCAM_CAMERA_HEIGHT, &(info->preview_height),
608 MMCAM_VIDEO_WIDTH, &(info->video_width),
609 MMCAM_VIDEO_HEIGHT, &(info->video_height),
610 MMCAM_FILE_FORMAT, &fileformat,
611 MMCAM_TARGET_FILENAME, &temp_filename, &size,
612 MMCAM_TARGET_MAX_SIZE, &imax_size,
613 MMCAM_TARGET_TIME_LIMIT, &imax_time,
614 MMCAM_FILE_FORMAT, &(info->fileformat),
615 MMCAM_CAMERA_RECORDING_MOTION_RATE, &motion_rate,
616 MMCAM_ROOT_DIRECTORY, &hcamcorder->root_directory, &root_directory_length,
618 if (ret != MM_ERROR_NONE) {
619 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
621 goto _ERR_CAMCORDER_VIDEO_COMMAND;
624 if (temp_filename == NULL) {
625 _mmcam_dbg_err("filename is not set");
626 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
627 goto _ERR_CAMCORDER_VIDEO_COMMAND;
632 info->max_size = 0; /* do not check */
634 info->max_size = ((guint64)imax_size) << 10; /* to byte */
638 info->max_time = 0; /* do not check */
640 info->max_time = (guint64)((double)imax_time * (double)1000 * motion_rate); /* to millisecond */
642 dir_name = g_path_get_dirname(temp_filename);
644 ret = _mmcamcorder_get_storage_info(dir_name, hcamcorder->root_directory, &hcamcorder->storage_info);
646 _mmcam_dbg_err("get storage info failed");
649 return MM_ERROR_OUT_OF_STORAGE;
652 ret_free_space = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
654 _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "]", dir_name, free_space);
656 if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) {
657 /* MSDOS_SUPER_MAGIC : 0x4d44 */
658 if (file_system_type == MSDOS_SUPER_MAGIC &&
659 (info->max_size == 0 || info->max_size > FAT32_FILE_SYSTEM_MAX_SIZE)) {
660 _mmcam_dbg_warn("FAT32 and too large max[%"G_GUINT64_FORMAT"], set max as %"G_GUINT64_FORMAT,
661 info->max_size, FAT32_FILE_SYSTEM_MAX_SIZE);
662 info->max_size = FAT32_FILE_SYSTEM_MAX_SIZE;
664 _mmcam_dbg_warn("file system 0x%x, max size %"G_GUINT64_FORMAT,
665 file_system_type, info->max_size);
668 _mmcam_dbg_warn("_mmcamcorder_get_file_system_type failed");
674 _mmcam_dbg_err("failed to get directory name");
678 if ((ret_free_space == -1) || free_space <= (_MMCAMCORDER_MINIMUM_SPACE<<1)) {
679 _mmcam_dbg_err("OUT of STORAGE [ret_free_space:%d or free space [%" G_GUINT64_FORMAT "] is smaller than [%d]",
680 ret_free_space, free_space, (_MMCAMCORDER_MINIMUM_SPACE<<1));
681 return MM_ERROR_OUT_OF_STORAGE;
684 g_mutex_lock(&hcamcorder->task_thread_lock);
685 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
686 hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
687 /* Play record start sound */
688 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_START, FALSE);
690 g_mutex_unlock(&hcamcorder->task_thread_lock);
692 _mmcam_dbg_warn("video size [%dx%d]", info->video_width, info->video_height);
694 if (info->video_width == 0 || info->video_height == 0) {
695 _mmcam_dbg_warn("video size is invalid [%dx%d] use preview size [%dx%d]",
696 info->video_width, info->video_height, info->preview_width, info->preview_height);
697 info->video_width = info->preview_width;
698 info->video_height = info->preview_height;
701 if (info->support_dual_stream) {
702 _mmcam_dbg_warn("DUAL STREAM MODE");
704 info->record_dual_stream = TRUE;
706 /* No need to restart preview */
707 info->restart_preview = FALSE;
709 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width);
710 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height);
711 } else if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
712 info->preview_width == info->video_width &&
713 info->preview_height == info->video_height) {
714 _mmcam_dbg_log("H264 preview mode and same resolution");
716 /* No need to restart preview */
717 info->restart_preview = FALSE;
719 /* always need to restart preview */
720 info->restart_preview = TRUE;
723 /* set recording hint */
724 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", TRUE);
726 if (info->restart_preview) {
727 /* stop preview and set new size */
728 _mmcam_dbg_log("restart preview");
730 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
731 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
732 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
734 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
736 /* check decoder recreation */
737 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
738 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
739 ret = MM_ERROR_CAMCORDER_INTERNAL;
740 goto _ERR_CAMCORDER_VIDEO_COMMAND;
743 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
744 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
745 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
747 if (ret != MM_ERROR_NONE)
748 goto _ERR_CAMCORDER_VIDEO_COMMAND;
750 if (!_mmcamcorder_set_camera_resolution(handle, info->video_width, info->video_height)) {
751 ret = MM_ERROR_CAMCORDER_INTERNAL;
752 goto _ERR_CAMCORDER_VIDEO_COMMAND;
755 /* Start preview again with new setting */
756 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
757 if (ret != MM_ERROR_NONE)
758 goto _ERR_CAMCORDER_VIDEO_COMMAND;
760 if (motion_rate < 1.0) {
761 _mmcam_dbg_warn("wait for stabilization of frame");
765 _mmcam_dbg_log("no need to restart preview");
768 _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
769 CONFIGURE_CATEGORY_MAIN_RECORD,
773 _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
774 CONFIGURE_CATEGORY_MAIN_RECORD,
775 "PassFirstVideoFrame",
776 &(sc->pass_first_vframe));
778 _mmcam_dbg_log("Drop video frame count[%d], Pass fisrt video frame count[%d]",
779 sc->drop_vframe, sc->pass_first_vframe);
781 info->record_drop_count = (guint)motion_rate;
782 info->record_motion_rate = motion_rate;
783 if (sc->is_modified_rate)
784 info->record_timestamp_ratio = (_MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE/motion_rate);
786 info->record_timestamp_ratio = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
788 _mmcam_dbg_warn("recording fps %d, motion rate %f, timestamp_ratio %f",
789 fps, info->record_motion_rate, info->record_timestamp_ratio);
791 /* set push buffer flag */
792 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT;
793 info->base_video_ts = 0;
795 /* connect video stream cb signal */
796 /*130826 Connect video stream cb for handling fast record frame cb*/
797 if (info->record_dual_stream) {
798 if (_mmcamcorder_connect_video_stream_cb_signal((MMHandleType)hcamcorder) != MM_ERROR_NONE)
799 goto _ERR_CAMCORDER_VIDEO_COMMAND;
802 /* start video stream */
803 if (info->record_dual_stream) {
804 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
806 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
808 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_START");
809 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_START);
811 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
813 _mmcam_dbg_err("could not get camera control");
817 /* check pre-created encode pipeline */
818 g_mutex_lock(&hcamcorder->task_thread_lock);
819 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
820 hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
821 /* create encoding pipeline */
822 ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
823 if (ret != MM_ERROR_NONE) {
824 g_mutex_unlock(&hcamcorder->task_thread_lock);
825 goto _ERR_CAMCORDER_VIDEO_COMMAND;
828 g_mutex_unlock(&hcamcorder->task_thread_lock);
830 /* check recording start sound */
831 _mmcamcorder_sound_solo_play_wait(handle);
833 /**< To fix video recording hanging
834 1. use gst_element_set_start_time() instead of gst_pipeline_set_new_stream_time()
835 2. Set (GstClockTime)1 instead of (GstClockTime)0. Because of strict check in gstreamer 0.25,
836 basetime wouldn't change if you set (GstClockTime)0.
837 3. Move set start time position below PAUSED of pipeline.
840 gst_element_set_start_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), (GstClockTime)1);
841 gst_element_set_start_time(GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), (GstClockTime)1);
844 info->video_frame_count = 0;
845 info->is_firstframe = TRUE;
846 info->audio_frame_count = 0;
848 sc->ferror_send = FALSE;
849 sc->ferror_count = 0;
850 hcamcorder->error_occurs = FALSE;
851 sc->bget_eos = FALSE;
852 sc->muxed_stream_offset = 0;
854 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
855 if (ret != MM_ERROR_NONE) {
856 /* stop video stream */
857 if (info->record_dual_stream) {
858 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
860 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
862 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
863 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
865 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
867 _mmcam_dbg_err("failed to get camera control");
871 /* Remove recorder pipeline and recording file which size maybe zero */
872 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
873 if (info->filename) {
874 _mmcam_dbg_log("file delete(%s)", info->filename);
875 unlink(info->filename);
877 goto _ERR_CAMCORDER_VIDEO_COMMAND;
880 /*set the camera control to create the GOP so that video record will get a new key frame*/
881 if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
882 GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
883 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
884 controls = gst_camera_control_list_channels(CameraControl);
885 if (controls != NULL) {
886 for (item = controls ; item && item->data ; item = item->next) {
887 CameraControlChannel = item->data;
888 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
889 if (!strcmp(CameraControlChannel->label, "new-gop")) {
890 /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
896 _mmcam_dbg_warn("failed to find new-gop control channel");
899 _mmcam_dbg_warn("Can't cast Video source into camera control or not H264 prevew format[%d]",
900 sc->info_image->preview_format);
905 if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
906 GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
907 /* generate and I-frame on resuming */
908 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
909 controls = gst_camera_control_list_channels(CameraControl);
910 if (controls != NULL) {
911 for (item = controls ; item && item->data ; item = item->next) {
912 CameraControlChannel = item->data;
913 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
914 if (!strcmp(CameraControlChannel->label, "new-gop")) {
915 /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
921 _mmcam_dbg_warn("failed to find new-gop control channel");
925 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
927 _mmcam_dbg_log("Object property settings done");
931 case _MMCamcorder_CMD_PAUSE:
933 if (info->b_commiting) {
934 _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
935 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
938 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
939 if (sc->audio_disable) {
940 /* check only video frame */
941 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
943 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
944 _mmcam_dbg_err("Pause fail, frame count %llu", info->video_frame_count);
945 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
947 _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %llu", count, info->video_frame_count);
950 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
952 /* check both of video and audio frame */
953 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
955 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
956 _mmcam_dbg_err("Pause fail, frame count VIDEO[%llu], AUDIO [%llu]",
957 info->video_frame_count, info->audio_frame_count);
958 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
960 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu]",
961 count, info->video_frame_count, info->audio_frame_count);
964 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
968 /* block encodebin */
969 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
972 case _MMCamcorder_CMD_CANCEL:
974 if (info->b_commiting) {
975 _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
976 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
979 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
981 if (hcamcorder->capture_in_recording == FALSE) {
983 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
984 _mmcam_dbg_err("Failed to Wait capture data");
985 hcamcorder->capture_in_recording = FALSE;
988 _mmcam_dbg_warn("Waiting for capture data - retrial [%d]", count);
991 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
994 /* block push buffer */
995 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
997 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
998 if (ret != MM_ERROR_NONE)
999 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1001 /* set recording hint */
1002 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1004 /* stop video stream */
1005 if (info->record_dual_stream) {
1006 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1007 if (CameraControl) {
1008 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1010 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1011 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1013 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1015 _mmcam_dbg_err("failed to get camera control");
1019 if (info->restart_preview) {
1020 /* restart preview */
1021 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1022 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1023 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1025 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
1027 /* check decoder recreation */
1028 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1029 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1030 ret = MM_ERROR_CAMCORDER_INTERNAL;
1033 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1034 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1035 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1037 if (ret != MM_ERROR_NONE)
1038 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1040 /* reset restart_preview for inset window layout */
1041 info->restart_preview = FALSE;
1043 if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1044 ret = MM_ERROR_CAMCORDER_INTERNAL;
1045 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1048 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
1049 if (ret != MM_ERROR_NONE)
1050 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1053 /* remove target file */
1054 if (info->filename) {
1055 _mmcam_dbg_log("file delete(%s)", info->filename);
1056 unlink(info->filename);
1059 sc->isMaxsizePausing = FALSE;
1060 sc->isMaxtimePausing = FALSE;
1062 sc->display_interval = 0;
1063 sc->previous_slot_time = 0;
1064 info->video_frame_count = 0;
1065 info->audio_frame_count = 0;
1067 hcamcorder->capture_in_recording = FALSE;
1070 case _MMCamcorder_CMD_COMMIT:
1072 if (info->b_commiting) {
1073 _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command);
1074 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
1076 _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
1077 info->b_commiting = TRUE;
1078 sc->bget_eos = FALSE;
1081 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
1082 if (sc->audio_disable) {
1083 /* check only video frame */
1084 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1085 hcamcorder->capture_in_recording == FALSE) {
1087 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1088 _mmcam_dbg_err("Commit fail, frame count is %llu, capturing %d",
1089 info->video_frame_count, hcamcorder->capture_in_recording);
1091 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
1092 _mmcam_dbg_warn("video frames are enough. keep going...");
1094 info->b_commiting = FALSE;
1095 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1098 _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %llu, capturing %d",
1099 count, info->video_frame_count, hcamcorder->capture_in_recording);
1102 /* check both of video and audio frame */
1103 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1104 info->audio_frame_count &&
1105 hcamcorder->capture_in_recording == FALSE) {
1107 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1108 _mmcam_dbg_err("Commit fail, VIDEO[%llu], AUDIO [%llu], capturing %d",
1109 info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1111 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
1112 _mmcam_dbg_warn("video/audio frames are enough. keep going...");
1114 info->b_commiting = FALSE;
1115 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1118 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1120 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu], capturing %d",
1121 count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1125 if (hcamcorder->capture_in_recording) {
1126 gint64 end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND);
1127 if (_MMCAMCORDER_CMD_WAIT_UNTIL(handle, end_time)) {
1128 _mmcam_dbg_warn("signal received");
1130 _mmcam_dbg_warn("timeout");
1133 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
1137 /* block push buffer */
1138 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1139 _mmcam_dbg_log("block push buffer to appsrc");
1141 if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
1142 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
1143 _mmcam_dbg_warn("VIDEO: send eos to appsrc done");
1145 _mmcam_dbg_err("VIDEO: send EOS failed");
1146 info->b_commiting = FALSE;
1147 ret = MM_ERROR_CAMCORDER_INTERNAL;
1148 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1151 _mmcam_dbg_err("No video stream source");
1152 info->b_commiting = FALSE;
1153 ret = MM_ERROR_CAMCORDER_INTERNAL;
1154 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1157 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
1158 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
1159 _mmcam_dbg_warn("AUDIO: send eos to audiosrc done");
1161 _mmcam_dbg_err("AUDIO: send EOS failed");
1162 info->b_commiting = FALSE;
1163 ret = MM_ERROR_CAMCORDER_INTERNAL;
1164 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1167 _mmcam_dbg_log("No audio stream");
1171 sc->display_interval = 0;
1172 sc->previous_slot_time = 0;
1175 _mmcam_dbg_log("Start to wait EOS");
1176 ret = _mmcamcorder_get_eos_message(handle);
1177 if (ret != MM_ERROR_NONE) {
1178 info->b_commiting = FALSE;
1179 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1183 hcamcorder->capture_in_recording = FALSE;
1187 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1188 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1191 return MM_ERROR_NONE;
1193 _ERR_CAMCORDER_VIDEO_COMMAND:
1194 if (command == _MMCamcorder_CMD_RECORD)
1195 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1201 int _mmcamcorder_video_handle_eos(MMHandleType handle)
1203 int ret = MM_ERROR_NONE;
1205 guint64 file_size = 0;
1207 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1208 _MMCamcorderSubContext *sc = NULL;
1209 _MMCamcorderVideoInfo *info = NULL;
1210 _MMCamcorderMsgItem msg;
1211 MMCamRecordingReport *report = NULL;
1213 mmf_return_val_if_fail(hcamcorder, FALSE);
1215 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1216 mmf_return_val_if_fail(sc, FALSE);
1217 mmf_return_val_if_fail(sc->info_video, FALSE);
1219 info = sc->info_video;
1223 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1224 /* Play record stop sound */
1225 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1227 _mmcam_dbg_warn("Play stop sound through pulseaudio");
1229 _mmcamcorder_sound_init(handle);
1231 _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, TRUE);
1233 _mmcamcorder_sound_finalize(handle);
1236 /* remove blocking part */
1237 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1239 mm_camcorder_get_attributes(handle, NULL,
1240 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1243 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1244 if (ret != MM_ERROR_NONE)
1245 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1247 /* set recording hint */
1248 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1250 /* stop video stream */
1251 if (info->record_dual_stream) {
1252 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1254 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1256 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1257 gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1259 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1261 _mmcam_dbg_err("failed to get camera control");
1265 if (enabletag && !(sc->ferror_send)) {
1266 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1268 _mmcam_dbg_log("Writing location information SUCCEEDED !!");
1270 _mmcam_dbg_err("Writing location information FAILED !!");
1274 /* Check file size */
1275 if (info->max_size > 0) {
1276 _mmcamcorder_get_file_size(info->filename, &file_size);
1277 _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
1278 info->max_size, file_size);
1280 if (file_size > info->max_size) {
1281 _MMCamcorderMsgItem message;
1282 _mmcam_dbg_err("File size is greater than max size !!");
1283 message.id = MM_MESSAGE_CAMCORDER_ERROR;
1284 message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1285 _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1289 if (info->restart_preview) {
1291 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1292 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1293 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1295 _mmcam_dbg_log("Set state of pipeline as READY");
1296 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1298 /* check decoder recreation */
1299 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1300 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1301 ret = MM_ERROR_CAMCORDER_INTERNAL;
1305 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1306 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1307 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1309 if (ret != MM_ERROR_NONE) {
1310 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1311 msg.param.code = ret;
1312 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1313 _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1316 /* reset restart_preview for inset window layout */
1317 info->restart_preview = FALSE;
1319 /* recover preview size */
1320 _mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height);
1322 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1323 /* Do not return when error is occurred.
1324 Recording file was created successfully, but starting pipeline failed */
1325 if (ret != MM_ERROR_NONE) {
1326 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1327 msg.param.code = ret;
1328 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1329 _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1332 _mmcam_dbg_log("No need to restart preview");
1335 /* Send recording report to application */
1336 msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1337 report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1339 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1341 report->recording_filename = g_strdup(info->filename);
1342 msg.param.data = report;
1344 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1348 sc->pipeline_time = 0;
1350 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1351 sc->isMaxtimePausing = FALSE;
1352 hcamcorder->error_occurs = FALSE;
1354 info->video_frame_count = 0;
1355 info->audio_frame_count = 0;
1357 info->b_commiting = FALSE;
1359 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1360 /* check recording stop sound */
1361 _mmcamcorder_sound_solo_play_wait(handle);
1364 _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1370 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1372 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1373 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1375 _MMCamcorderSubContext *sc = NULL;
1376 _MMCamcorderVideoInfo *videoinfo = NULL;
1377 _MMCamcorderMsgItem msg;
1378 guint64 buffer_size = 0;
1379 guint64 trailer_size = 0;
1380 guint64 max_size = 0;
1382 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1383 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1384 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1386 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1387 videoinfo = sc->info_video;
1389 /* get buffer size */
1390 if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1391 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1392 return GST_PAD_PROBE_OK;
1395 buffer_size = mapinfo.size;
1396 gst_buffer_unmap(buffer, &mapinfo);
1398 /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1400 g_mutex_lock(&videoinfo->size_check_lock);
1402 if (videoinfo->audio_frame_count == 0) {
1403 videoinfo->filesize += buffer_size;
1404 videoinfo->audio_frame_count++;
1405 g_mutex_unlock(&videoinfo->size_check_lock);
1406 return GST_PAD_PROBE_OK;
1409 if (sc->ferror_send || sc->isMaxsizePausing) {
1410 _mmcam_dbg_warn("Recording is paused, drop frames");
1411 g_mutex_unlock(&videoinfo->size_check_lock);
1412 return GST_PAD_PROBE_DROP;
1415 /* get trailer size */
1416 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1417 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1422 /* check max size of recorded file */
1423 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1424 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1425 GstState pipeline_state = GST_STATE_VOID_PENDING;
1426 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1427 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1428 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1429 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1430 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1432 if (!sc->isMaxsizePausing) {
1433 sc->isMaxsizePausing = TRUE;
1434 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1435 if (pipeline_state == GST_STATE_PLAYING)
1436 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1438 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1439 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1442 g_mutex_unlock(&videoinfo->size_check_lock);
1447 videoinfo->filesize += buffer_size;
1448 videoinfo->audio_frame_count++;
1450 g_mutex_unlock(&videoinfo->size_check_lock);
1452 return GST_PAD_PROBE_OK;
1456 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1461 guint64 free_space = 0;
1462 guint64 buffer_size = 0;
1463 guint64 trailer_size = 0;
1464 guint64 queued_buffer = 0;
1465 guint64 max_size = 0;
1466 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1468 storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1470 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1471 _MMCamcorderMsgItem msg;
1472 _MMCamcorderSubContext *sc = NULL;
1473 _MMCamcorderVideoInfo *videoinfo = NULL;
1475 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1476 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1478 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1479 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1480 videoinfo = sc->info_video;
1482 /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1483 if (sc->ferror_send) {
1484 _mmcam_dbg_warn("file write error, drop frames");
1485 return GST_PAD_PROBE_DROP;
1488 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1489 buffer_size = mapinfo.size;
1490 gst_buffer_unmap(buffer, &mapinfo);
1492 videoinfo->video_frame_count++;
1493 if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1494 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1495 info->video_frame_count); */
1496 g_mutex_lock(&videoinfo->size_check_lock);
1497 videoinfo->filesize += buffer_size;
1498 g_mutex_unlock(&videoinfo->size_check_lock);
1499 return GST_PAD_PROBE_OK;
1502 /* get trailer size */
1503 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1504 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1509 /* check free space */
1510 ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1512 _mmcam_dbg_err("Error occured. [%d]", ret);
1513 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1514 sc->ferror_send = TRUE;
1516 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1517 msg.param.code = MM_ERROR_FILE_READ;
1519 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1524 return GST_PAD_PROBE_DROP; /* skip this buffer */
1527 if (free_space == 0) {
1528 /* check storage state */
1529 storage_get_state(hcamcorder->storage_info.id, &storage_state);
1531 _mmcam_dbg_warn("storage state %d", storage_state);
1533 if (storage_state == STORAGE_STATE_REMOVED ||
1534 storage_state == STORAGE_STATE_UNMOUNTABLE) {
1535 _mmcam_dbg_err("storage was removed!");
1537 _MMCAMCORDER_LOCK(hcamcorder);
1539 if (sc->ferror_send == FALSE) {
1540 _mmcam_dbg_err("OUT_OF_STORAGE error");
1542 sc->ferror_send = TRUE;
1544 _MMCAMCORDER_UNLOCK(hcamcorder);
1546 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1547 msg.param.code = MM_ERROR_OUT_OF_STORAGE;
1549 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1551 _MMCAMCORDER_UNLOCK(hcamcorder);
1552 _mmcam_dbg_warn("error was already sent");
1555 return GST_PAD_PROBE_DROP;
1559 /* get queued buffer size */
1560 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
1561 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
1564 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
1565 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1568 queued_buffer = aq_size + vq_size;
1570 if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1571 _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
1572 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
1573 " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
1574 free_space, trailer_size, buffer_size, queued_buffer);
1576 if (!sc->isMaxsizePausing) {
1577 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1578 sc->isMaxsizePausing = TRUE;
1580 msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
1581 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1584 return GST_PAD_PROBE_DROP;
1587 g_mutex_lock(&videoinfo->size_check_lock);
1589 /* check max size of recorded file */
1590 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1591 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1592 GstState pipeline_state = GST_STATE_VOID_PENDING;
1593 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1594 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1595 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1596 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1597 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1599 if (!sc->isMaxsizePausing) {
1600 sc->isMaxsizePausing = TRUE;
1601 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1602 if (pipeline_state == GST_STATE_PLAYING)
1603 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1605 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1606 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1609 g_mutex_unlock(&videoinfo->size_check_lock);
1611 return GST_PAD_PROBE_DROP;
1614 videoinfo->filesize += (guint64)buffer_size;
1617 _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
1620 g_mutex_unlock(&videoinfo->size_check_lock);
1622 return GST_PAD_PROBE_OK;
1626 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1628 guint64 trailer_size = 0;
1629 guint64 rec_pipe_time = 0;
1630 unsigned int remained_time = 0;
1632 GstClockTime b_time;
1634 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1635 _MMCamcorderMsgItem msg;
1636 _MMCamcorderSubContext *sc = NULL;
1637 _MMCamcorderVideoInfo *videoinfo = NULL;
1639 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1641 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1642 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1644 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1645 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1646 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1648 videoinfo = sc->info_video;
1650 b_time = GST_BUFFER_PTS(buffer);
1652 rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1654 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1655 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1660 /* check max time */
1661 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1662 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1663 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1665 if (!sc->isMaxtimePausing) {
1666 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1668 sc->isMaxtimePausing = TRUE;
1670 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1671 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1672 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1673 msg.param.recording_status.remained_time = 0;
1674 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1676 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1677 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1680 return GST_PAD_PROBE_DROP;
1683 /* calculate remained time can be recorded */
1684 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1685 remained_time = videoinfo->max_time - rec_pipe_time;
1686 } else if (videoinfo->max_size > 0) {
1687 long double max_size = (long double)videoinfo->max_size;
1688 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1690 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1693 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1694 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1695 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1696 msg.param.recording_status.remained_time = remained_time;
1697 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1700 _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1701 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1704 if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1705 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1708 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1709 record_motion_rate, videoinfo->record_drop_count);
1712 /* drop some frame if fast motion */
1713 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1714 if (record_motion_rate != (videoinfo->record_drop_count++)) {
1716 _mmcam_dbg_warn("drop frame");
1718 return GST_PAD_PROBE_DROP;
1721 videoinfo->record_drop_count = 1;
1723 _mmcam_dbg_warn("pass frame");
1727 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1728 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1731 return GST_PAD_PROBE_OK;
1735 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1737 _MMCamcorderMsgItem msg;
1738 guint64 trailer_size = 0;
1739 guint64 rec_pipe_time = 0;
1740 _MMCamcorderSubContext *sc = NULL;
1741 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1742 _MMCamcorderVideoInfo *videoinfo = NULL;
1743 unsigned int remained_time = 0;
1744 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1746 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1747 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1748 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1750 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1751 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1752 mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1754 videoinfo = sc->info_video;
1756 if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1757 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1758 return GST_PAD_PROBE_OK;
1761 rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1763 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1764 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1769 /* calculate remained time can be recorded */
1770 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1771 remained_time = videoinfo->max_time - rec_pipe_time;
1772 } else if (videoinfo->max_size > 0) {
1773 long double max_size = (long double)videoinfo->max_size;
1774 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1776 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1779 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1780 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1781 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1783 if (!sc->isMaxtimePausing) {
1784 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1786 sc->isMaxtimePausing = TRUE;
1788 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1789 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1790 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1791 msg.param.recording_status.remained_time = 0;
1792 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1794 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1795 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1798 return GST_PAD_PROBE_DROP;
1801 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1802 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1803 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1804 msg.param.recording_status.remained_time = remained_time;
1805 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1808 _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1809 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1812 return GST_PAD_PROBE_OK;
1816 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1818 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1819 double volume = 0.0;
1822 int err = MM_ERROR_UNKNOWN;
1823 char *err_name = NULL;
1824 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1827 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1828 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1830 /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1831 err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1832 MMCAM_AUDIO_VOLUME, &volume,
1833 MMCAM_AUDIO_FORMAT, &format,
1834 MMCAM_AUDIO_CHANNEL, &channel,
1836 if (err != MM_ERROR_NONE) {
1837 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1838 SAFE_FREE(err_name);
1842 memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1844 gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1846 /* Set audio stream NULL */
1848 memset(mapinfo.data, 0, mapinfo.size);
1850 /* CALL audio stream callback */
1851 if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1852 MMCamcorderAudioStreamDataType stream;
1854 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1855 _mmcam_dbg_warn("Not ready for stream callback");
1856 gst_buffer_unmap(buffer, &mapinfo);
1857 return GST_PAD_PROBE_OK;
1860 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1861 GST_BUFFER_DATA(buffer), width, height, format);*/
1863 stream.data = (void *)mapinfo.data;
1864 stream.format = format;
1865 stream.channel = channel;
1866 stream.length = mapinfo.size;
1867 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1869 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1871 if (hcamcorder->astream_cb)
1872 hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1874 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1877 gst_buffer_unmap(buffer, &mapinfo);
1878 return GST_PAD_PROBE_OK;
1882 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1884 gboolean bret = FALSE;
1886 switch (fileformat) {
1887 case MM_FILE_FORMAT_3GP:
1888 case MM_FILE_FORMAT_MP4:
1889 bret = __mmcamcorder_add_metadata_mp4(handle);
1892 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1900 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1904 guint64 udta_size = 0;
1905 gint64 current_pos = 0;
1906 gint64 moov_pos = 0;
1907 gint64 udta_pos = 0;
1908 gdouble longitude = 0;
1909 gdouble latitude = 0;
1910 gdouble altitude = 0;
1912 int orientation = 0;
1914 char *err_name = NULL;
1915 char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1916 _MMCamcorderLocationInfo location_info = {0, 0, 0};
1917 _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1919 _MMCamcorderVideoInfo *info = NULL;
1920 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1921 _MMCamcorderSubContext *sc = NULL;
1923 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1924 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1926 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1927 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1931 info = sc->info_video;
1933 f = fopen64(info->filename, "rb+");
1935 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1936 _mmcam_dbg_err("file open failed [%s]", err_msg);
1940 mm_camcorder_get_attributes(handle, &err_name,
1941 MMCAM_TAG_LATITUDE, &latitude,
1942 MMCAM_TAG_LONGITUDE, &longitude,
1943 MMCAM_TAG_ALTITUDE, &altitude,
1944 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1945 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1948 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1949 SAFE_FREE(err_name);
1952 location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1953 location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1954 location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1955 geo_info.longitude = longitude *10000;
1956 geo_info.latitude = latitude *10000;
1957 geo_info.altitude = altitude *10000;
1958 /* find udta container.
1959 if, there are udta container, write loci box after that
1960 else, make udta container and write loci box. */
1961 if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1964 _mmcam_dbg_log("find udta container");
1967 if (fseek(f, -8L, SEEK_CUR) != 0)
1970 udta_pos = ftello(f);
1974 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1976 _mmcam_dbg_log("recorded file fread %d", nread);
1978 udta_size = _mmcamcorder_get_container_size(buf);
1980 /* goto end of udta and write 'loci' box */
1981 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1985 if (!_mmcamcorder_write_loci(f, location_info)) {
1986 _mmcam_dbg_err("failed to write loci");
1990 if (!_mmcamcorder_write_geodata(f, geo_info)) {
1991 _mmcam_dbg_err("failed to write geodata");
1996 current_pos = ftello(f);
1997 if (current_pos < 0)
2000 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
2003 _mmcam_dbg_log("No udta container");
2004 if (fseek(f, 0, SEEK_END) != 0)
2007 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
2008 _mmcam_dbg_err("failed to write udta");
2013 /* find moov container.
2014 update moov container size. */
2015 if ((current_pos = ftello(f)) < 0)
2018 if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
2019 gint64 internal_pos = ftello(f);
2021 _mmcam_dbg_log("found moov container");
2022 if (fseek(f, -8L, SEEK_CUR) != 0)
2025 moov_pos = ftello(f);
2029 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
2032 /* add orientation info */
2033 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
2034 _mmcam_dbg_err("fseek failed : errno %d", errno);
2038 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
2039 _mmcam_dbg_err("failed to find [trak] tag");
2043 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
2044 _mmcam_dbg_err("failed to find [tkhd] tag");
2048 _mmcam_dbg_log("found [tkhd] tag");
2050 /* seek to start position of composition matrix */
2051 fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR);
2053 /* update composition matrix for orientation */
2054 _mmcamcorder_update_composition_matrix(f, orientation);
2056 _mmcam_dbg_err("No 'moov' container");
2068 _mmcam_dbg_err("ftell() returns negative value.");
2074 int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
2076 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2077 _MMCamcorderSubContext *sc = NULL;
2079 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2081 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2082 mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2084 /* check video source element */
2085 if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
2086 _mmcam_dbg_warn("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
2087 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
2088 _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
2089 G_CALLBACK(__mmcamcorder_video_stream_cb),
2091 return MM_ERROR_NONE;
2093 _mmcam_dbg_err("videosrc element is not created yet");
2094 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
2099 int _mmcamcorder_video_prepare_record(MMHandleType handle)
2101 int ret = MM_ERROR_NONE;
2103 _MMCamcorderVideoInfo *info = NULL;
2104 _MMCamcorderSubContext *sc = NULL;
2105 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2107 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2109 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2110 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2111 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2113 info = sc->info_video;
2115 _mmcam_dbg_warn("start");
2117 /* create encoding pipeline */
2118 ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2119 if (ret != MM_ERROR_NONE)
2120 goto _ERR_PREPARE_RECORD;
2122 if (info->filename == NULL) {
2123 char *temp_filename = NULL;
2126 mm_camcorder_get_attributes(handle, NULL,
2127 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2130 info->filename = g_strdup(temp_filename);
2132 if (!info->filename) {
2133 _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
2134 goto _ERR_PREPARE_RECORD;
2138 _mmcam_dbg_log("Record file name [%s]", info->filename);
2140 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2141 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2143 /* Adjust display FPS */
2144 sc->display_interval = 0;
2145 sc->previous_slot_time = 0;
2147 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2148 if (ret != MM_ERROR_NONE)
2149 goto _ERR_PREPARE_RECORD;
2151 _mmcam_dbg_warn("done");
2155 _ERR_PREPARE_RECORD:
2156 /* Remove recorder pipeline and recording file which size maybe zero */
2157 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2158 if (info && info->filename) {
2159 _mmcam_dbg_log("file delete(%s)", info->filename);
2160 unlink(info->filename);