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);
410 #ifdef _MMCAMCORDER_MURPHY_WAIT_TO_RELEASE_SUB_RESOURCE
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);
417 #endif /* _MMCAMCORDER_MURPHY_WAIT_TO_RELEASE_SUB_RESOURCE */
420 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
422 _mmcam_dbg_warn("unlock resource");
423 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
426 return MM_ERROR_NONE;
430 int _mmcamcorder_remove_recorder_pipeline(MMHandleType handle)
432 int ret = MM_ERROR_NONE;
433 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
434 _MMCamcorderSubContext *sc = NULL;
438 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
439 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
440 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
442 _mmcam_dbg_log("start");
444 if (!sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
445 _mmcam_dbg_warn("pipeline is not existed.");
446 return MM_ERROR_NONE;
449 _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_VIDEOREC);
451 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
452 if (ret != MM_ERROR_NONE) {
453 _mmcam_dbg_err("Faile to change encode main pipeline [0x%x]", ret);
457 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
459 /* remove audio pipeline first */
460 ret = _mmcamcorder_remove_audio_pipeline(handle);
461 if (ret != MM_ERROR_NONE) {
462 _mmcam_dbg_err("Fail to remove audio pipeline");
466 ret = _mmcamcorder_remove_encode_pipeline(handle);
467 if (ret != MM_ERROR_NONE) {
468 _mmcam_dbg_err("Fail to remove encoder pipeline");
472 /* Remove pipeline message callback */
473 if (hcamcorder->encode_pipeline_cb_event_id != 0) {
474 g_source_remove(hcamcorder->encode_pipeline_cb_event_id);
475 hcamcorder->encode_pipeline_cb_event_id = 0;
478 /* Remove remained message */
480 GstMessage *gst_msg = NULL;
481 while ((gst_msg = gst_bus_pop(bus)) != NULL) {
482 _mmcamcorder_pipeline_cb_message(bus, gst_msg, (gpointer)hcamcorder);
483 gst_message_unref(gst_msg);
486 gst_object_unref(bus);
490 _mmcam_dbg_log("done");
496 int _mmcamcorder_video_command(MMHandleType handle, int command)
501 int ret = MM_ERROR_NONE;
502 double motion_rate = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
503 char *err_name = NULL;
504 char *temp_filename = NULL;
505 GstCameraControl *CameraControl = NULL;
506 GstCameraControlChannel *CameraControlChannel = NULL;
507 const GList *controls = NULL;
508 const GList *item = NULL;
511 GstElement *pipeline = NULL;
513 _MMCamcorderVideoInfo *info = NULL;
514 _MMCamcorderSubContext *sc = NULL;
515 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
517 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
519 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
520 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
521 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
522 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
524 info = sc->info_video;
526 _mmcam_dbg_log("Command(%d)", command);
528 pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
531 case _MMCamcorder_CMD_RECORD:
533 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED) {
539 int ret_free_space = 0;
540 char *dir_name = NULL;
541 guint64 free_space = 0;
542 int file_system_type = 0;
543 int root_directory_length = 0;
546 _mmcam_dbg_log("Record Start - dual stream %d", info->support_dual_stream);
548 #ifdef _MMCAMCORDER_MURPHY_SUPPORT
549 /* check connection */
550 ret = _mmcamcorder_resource_check_connection(&hcamcorder->resource_manager_sub);
551 if (ret != MM_ERROR_NONE)
552 goto _ERR_CAMCORDER_VIDEO_COMMAND;
554 /* create resource set */
555 ret = _mmcamcorder_resource_create_resource_set(&hcamcorder->resource_manager_sub);
556 if (ret != MM_ERROR_NONE)
557 goto _ERR_CAMCORDER_VIDEO_COMMAND;
559 hcamcorder->resource_manager_sub.acquire_count = 0;
561 /* prepare resource manager for H/W encoder */
562 ret = _mmcamcorder_resource_manager_prepare(&hcamcorder->resource_manager_sub, MM_CAMCORDER_RESOURCE_TYPE_VIDEO_ENCODER);
563 if (ret != MM_ERROR_NONE) {
564 _mmcam_dbg_err("could not prepare for video_encoder resource");
565 ret = MM_ERROR_CAMCORDER_INTERNAL;
566 goto _ERR_CAMCORDER_VIDEO_COMMAND;
569 /* acquire resources */
570 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
572 ret = _mmcamcorder_resource_manager_acquire(&hcamcorder->resource_manager_sub);
573 if (ret != MM_ERROR_NONE) {
574 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
575 _mmcam_dbg_err("could not acquire resource");
576 goto _ERR_CAMCORDER_VIDEO_COMMAND;
579 if (hcamcorder->resource_manager_sub.acquire_remain > 0) {
582 _mmcam_dbg_warn("wait for resource state change");
584 /* wait for resource state change */
585 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
587 if (_MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time)) {
588 _mmcam_dbg_warn("signal received");
590 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
591 _mmcam_dbg_err("timeout");
592 ret = MM_ERROR_RESOURCE_INTERNAL;
593 goto _ERR_CAMCORDER_VIDEO_COMMAND;
596 _mmcam_dbg_log("already acquired");
599 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
600 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
602 /* init record_dual_stream */
603 info->record_dual_stream = FALSE;
605 ret = mm_camcorder_get_attributes(handle, &err_name,
606 MMCAM_CAMERA_FPS, &fps,
607 MMCAM_CAMERA_WIDTH, &(info->preview_width),
608 MMCAM_CAMERA_HEIGHT, &(info->preview_height),
609 MMCAM_VIDEO_WIDTH, &(info->video_width),
610 MMCAM_VIDEO_HEIGHT, &(info->video_height),
611 MMCAM_FILE_FORMAT, &fileformat,
612 MMCAM_TARGET_FILENAME, &temp_filename, &size,
613 MMCAM_TARGET_MAX_SIZE, &imax_size,
614 MMCAM_TARGET_TIME_LIMIT, &imax_time,
615 MMCAM_FILE_FORMAT, &(info->fileformat),
616 MMCAM_CAMERA_RECORDING_MOTION_RATE, &motion_rate,
617 MMCAM_ROOT_DIRECTORY, &hcamcorder->root_directory, &root_directory_length,
619 if (ret != MM_ERROR_NONE) {
620 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
622 goto _ERR_CAMCORDER_VIDEO_COMMAND;
625 if (temp_filename == NULL) {
626 _mmcam_dbg_err("filename is not set");
627 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
628 goto _ERR_CAMCORDER_VIDEO_COMMAND;
633 info->max_size = 0; /* do not check */
635 info->max_size = ((guint64)imax_size) << 10; /* to byte */
639 info->max_time = 0; /* do not check */
641 info->max_time = (guint64)((double)imax_time * (double)1000 * motion_rate); /* to millisecond */
643 dir_name = g_path_get_dirname(temp_filename);
645 ret = _mmcamcorder_get_storage_info(dir_name, hcamcorder->root_directory, &hcamcorder->storage_info);
647 _mmcam_dbg_err("get storage info failed");
650 return MM_ERROR_OUT_OF_STORAGE;
653 ret_free_space = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
655 _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "]", dir_name, free_space);
657 if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) {
658 /* MSDOS_SUPER_MAGIC : 0x4d44 */
659 if (file_system_type == MSDOS_SUPER_MAGIC &&
660 (info->max_size == 0 || info->max_size > FAT32_FILE_SYSTEM_MAX_SIZE)) {
661 _mmcam_dbg_warn("FAT32 and too large max[%"G_GUINT64_FORMAT"], set max as %"G_GUINT64_FORMAT,
662 info->max_size, FAT32_FILE_SYSTEM_MAX_SIZE);
663 info->max_size = FAT32_FILE_SYSTEM_MAX_SIZE;
665 _mmcam_dbg_warn("file system 0x%x, max size %"G_GUINT64_FORMAT,
666 file_system_type, info->max_size);
669 _mmcam_dbg_warn("_mmcamcorder_get_file_system_type failed");
675 _mmcam_dbg_err("failed to get directory name");
679 if ((ret_free_space == -1) || free_space <= (_MMCAMCORDER_MINIMUM_SPACE<<1)) {
680 _mmcam_dbg_err("OUT of STORAGE [ret_free_space:%d or free space [%" G_GUINT64_FORMAT "] is smaller than [%d]",
681 ret_free_space, free_space, (_MMCAMCORDER_MINIMUM_SPACE<<1));
682 return MM_ERROR_OUT_OF_STORAGE;
685 g_mutex_lock(&hcamcorder->task_thread_lock);
686 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
687 hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
688 /* Play record start sound */
689 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_START, FALSE);
691 g_mutex_unlock(&hcamcorder->task_thread_lock);
693 _mmcam_dbg_warn("video size [%dx%d]", info->video_width, info->video_height);
695 if (info->video_width == 0 || info->video_height == 0) {
696 _mmcam_dbg_warn("video size is invalid [%dx%d] use preview size [%dx%d]",
697 info->video_width, info->video_height, info->preview_width, info->preview_height);
698 info->video_width = info->preview_width;
699 info->video_height = info->preview_height;
702 if (info->support_dual_stream) {
703 _mmcam_dbg_warn("DUAL STREAM MODE");
705 info->record_dual_stream = TRUE;
707 /* No need to restart preview */
708 info->restart_preview = FALSE;
710 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width);
711 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height);
712 } else if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
713 info->preview_width == info->video_width &&
714 info->preview_height == info->video_height) {
715 _mmcam_dbg_log("H264 preview mode and same resolution");
717 /* No need to restart preview */
718 info->restart_preview = FALSE;
720 /* always need to restart preview */
721 info->restart_preview = TRUE;
724 /* set recording hint */
725 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", TRUE);
727 if (info->restart_preview) {
728 /* stop preview and set new size */
729 _mmcam_dbg_log("restart preview");
731 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
732 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
733 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
735 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
737 /* check decoder recreation */
738 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
739 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
740 ret = MM_ERROR_CAMCORDER_INTERNAL;
741 goto _ERR_CAMCORDER_VIDEO_COMMAND;
744 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
745 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
746 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
748 if (ret != MM_ERROR_NONE)
749 goto _ERR_CAMCORDER_VIDEO_COMMAND;
751 if (!_mmcamcorder_set_camera_resolution(handle, info->video_width, info->video_height)) {
752 ret = MM_ERROR_CAMCORDER_INTERNAL;
753 goto _ERR_CAMCORDER_VIDEO_COMMAND;
756 /* Start preview again with new setting */
757 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
758 if (ret != MM_ERROR_NONE)
759 goto _ERR_CAMCORDER_VIDEO_COMMAND;
761 if (motion_rate < 1.0) {
762 _mmcam_dbg_warn("wait for stabilization of frame");
766 _mmcam_dbg_log("no need to restart preview");
769 _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
770 CONFIGURE_CATEGORY_MAIN_RECORD,
774 _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
775 CONFIGURE_CATEGORY_MAIN_RECORD,
776 "PassFirstVideoFrame",
777 &(sc->pass_first_vframe));
779 _mmcam_dbg_log("Drop video frame count[%d], Pass fisrt video frame count[%d]",
780 sc->drop_vframe, sc->pass_first_vframe);
782 info->record_drop_count = (guint)motion_rate;
783 info->record_motion_rate = motion_rate;
784 if (sc->is_modified_rate)
785 info->record_timestamp_ratio = (_MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE/motion_rate);
787 info->record_timestamp_ratio = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
789 _mmcam_dbg_warn("recording fps %d, motion rate %f, timestamp_ratio %f",
790 fps, info->record_motion_rate, info->record_timestamp_ratio);
792 /* set push buffer flag */
793 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT;
794 info->base_video_ts = 0;
796 /* connect video stream cb signal */
797 /*130826 Connect video stream cb for handling fast record frame cb*/
798 if (info->record_dual_stream) {
799 if (_mmcamcorder_connect_video_stream_cb_signal((MMHandleType)hcamcorder) != MM_ERROR_NONE)
800 goto _ERR_CAMCORDER_VIDEO_COMMAND;
803 /* start video stream */
804 if (info->record_dual_stream) {
805 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
807 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
809 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_START");
810 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_START);
812 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
814 _mmcam_dbg_err("could not get camera control");
818 /* check pre-created encode pipeline */
819 g_mutex_lock(&hcamcorder->task_thread_lock);
820 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
821 hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
822 /* create encoding pipeline */
823 ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
824 if (ret != MM_ERROR_NONE) {
825 g_mutex_unlock(&hcamcorder->task_thread_lock);
826 goto _ERR_CAMCORDER_VIDEO_COMMAND;
829 g_mutex_unlock(&hcamcorder->task_thread_lock);
831 /* check recording start sound */
832 _mmcamcorder_sound_solo_play_wait(handle);
834 /**< To fix video recording hanging
835 1. use gst_element_set_start_time() instead of gst_pipeline_set_new_stream_time()
836 2. Set (GstClockTime)1 instead of (GstClockTime)0. Because of strict check in gstreamer 0.25,
837 basetime wouldn't change if you set (GstClockTime)0.
838 3. Move set start time position below PAUSED of pipeline.
841 gst_element_set_start_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), (GstClockTime)1);
842 gst_element_set_start_time(GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), (GstClockTime)1);
845 info->video_frame_count = 0;
846 info->is_firstframe = TRUE;
847 info->audio_frame_count = 0;
849 sc->ferror_send = FALSE;
850 sc->ferror_count = 0;
851 hcamcorder->error_occurs = FALSE;
852 sc->bget_eos = FALSE;
853 sc->muxed_stream_offset = 0;
855 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
856 if (ret != MM_ERROR_NONE) {
857 /* stop video stream */
858 if (info->record_dual_stream) {
859 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
861 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
863 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
864 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
866 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
868 _mmcam_dbg_err("failed to get camera control");
872 /* Remove recorder pipeline and recording file which size maybe zero */
873 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
874 if (info->filename) {
875 _mmcam_dbg_log("file delete(%s)", info->filename);
876 unlink(info->filename);
878 goto _ERR_CAMCORDER_VIDEO_COMMAND;
881 /*set the camera control to create the GOP so that video record will get a new key frame*/
882 if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
883 GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
884 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
885 controls = gst_camera_control_list_channels(CameraControl);
886 if (controls != NULL) {
887 for (item = controls ; item && item->data ; item = item->next) {
888 CameraControlChannel = item->data;
889 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
890 if (!strcmp(CameraControlChannel->label, "new-gop")) {
891 /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
897 _mmcam_dbg_warn("failed to find new-gop control channel");
900 _mmcam_dbg_warn("Can't cast Video source into camera control or not H264 prevew format[%d]",
901 sc->info_image->preview_format);
906 if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
907 GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
908 /* generate and I-frame on resuming */
909 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
910 controls = gst_camera_control_list_channels(CameraControl);
911 if (controls != NULL) {
912 for (item = controls ; item && item->data ; item = item->next) {
913 CameraControlChannel = item->data;
914 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
915 if (!strcmp(CameraControlChannel->label, "new-gop")) {
916 /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
922 _mmcam_dbg_warn("failed to find new-gop control channel");
926 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
928 _mmcam_dbg_log("Object property settings done");
932 case _MMCamcorder_CMD_PAUSE:
934 if (info->b_commiting) {
935 _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
936 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
939 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
940 if (sc->audio_disable) {
941 /* check only video frame */
942 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
944 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
945 _mmcam_dbg_err("Pause fail, frame count %llu", info->video_frame_count);
946 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
948 _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %llu", count, info->video_frame_count);
951 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
953 /* check both of video and audio frame */
954 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
956 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
957 _mmcam_dbg_err("Pause fail, frame count VIDEO[%llu], AUDIO [%llu]",
958 info->video_frame_count, info->audio_frame_count);
959 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
961 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu]",
962 count, info->video_frame_count, info->audio_frame_count);
965 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
969 /* block encodebin */
970 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
973 case _MMCamcorder_CMD_CANCEL:
975 if (info->b_commiting) {
976 _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
977 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
980 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
982 if (hcamcorder->capture_in_recording == FALSE) {
984 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
985 _mmcam_dbg_err("Failed to Wait capture data");
986 hcamcorder->capture_in_recording = FALSE;
989 _mmcam_dbg_warn("Waiting for capture data - retrial [%d]", count);
992 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
995 /* block push buffer */
996 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
998 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
999 if (ret != MM_ERROR_NONE)
1000 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1002 /* set recording hint */
1003 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1005 /* stop video stream */
1006 if (info->record_dual_stream) {
1007 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1008 if (CameraControl) {
1009 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1011 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1012 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1014 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1016 _mmcam_dbg_err("failed to get camera control");
1020 if (info->restart_preview) {
1021 /* restart preview */
1022 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1023 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1024 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1026 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
1028 /* check decoder recreation */
1029 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1030 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1031 ret = MM_ERROR_CAMCORDER_INTERNAL;
1034 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1035 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1036 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1038 if (ret != MM_ERROR_NONE)
1039 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1041 /* reset restart_preview for inset window layout */
1042 info->restart_preview = FALSE;
1044 if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1045 ret = MM_ERROR_CAMCORDER_INTERNAL;
1046 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1049 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
1050 if (ret != MM_ERROR_NONE)
1051 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1054 /* remove target file */
1055 if (info->filename) {
1056 _mmcam_dbg_log("file delete(%s)", info->filename);
1057 unlink(info->filename);
1060 sc->isMaxsizePausing = FALSE;
1061 sc->isMaxtimePausing = FALSE;
1063 sc->display_interval = 0;
1064 sc->previous_slot_time = 0;
1065 info->video_frame_count = 0;
1066 info->audio_frame_count = 0;
1068 hcamcorder->capture_in_recording = FALSE;
1071 case _MMCamcorder_CMD_COMMIT:
1073 if (info->b_commiting) {
1074 _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command);
1075 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
1077 _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
1078 info->b_commiting = TRUE;
1079 sc->bget_eos = FALSE;
1082 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
1083 if (sc->audio_disable) {
1084 /* check only video frame */
1085 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1086 hcamcorder->capture_in_recording == FALSE) {
1088 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1089 _mmcam_dbg_err("Commit fail, frame count is %llu, capturing %d",
1090 info->video_frame_count, hcamcorder->capture_in_recording);
1092 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
1093 _mmcam_dbg_warn("video frames are enough. keep going...");
1095 info->b_commiting = FALSE;
1096 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1099 _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %llu, capturing %d",
1100 count, info->video_frame_count, hcamcorder->capture_in_recording);
1103 /* check both of video and audio frame */
1104 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1105 info->audio_frame_count &&
1106 hcamcorder->capture_in_recording == FALSE) {
1108 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1109 _mmcam_dbg_err("Commit fail, VIDEO[%llu], AUDIO [%llu], capturing %d",
1110 info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1112 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
1113 _mmcam_dbg_warn("video/audio frames are enough. keep going...");
1115 info->b_commiting = FALSE;
1116 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1119 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1121 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu], capturing %d",
1122 count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1126 if (hcamcorder->capture_in_recording) {
1127 gint64 end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND);
1128 if (_MMCAMCORDER_CMD_WAIT_UNTIL(handle, end_time)) {
1129 _mmcam_dbg_warn("signal received");
1131 _mmcam_dbg_warn("timeout");
1134 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
1138 /* block push buffer */
1139 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1140 _mmcam_dbg_log("block push buffer to appsrc");
1142 if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
1143 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
1144 _mmcam_dbg_warn("VIDEO: send eos to appsrc done");
1146 _mmcam_dbg_err("VIDEO: send EOS failed");
1147 info->b_commiting = FALSE;
1148 ret = MM_ERROR_CAMCORDER_INTERNAL;
1149 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1152 _mmcam_dbg_err("No video stream source");
1153 info->b_commiting = FALSE;
1154 ret = MM_ERROR_CAMCORDER_INTERNAL;
1155 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1158 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
1159 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
1160 _mmcam_dbg_warn("AUDIO: send eos to audiosrc done");
1162 _mmcam_dbg_err("AUDIO: send EOS failed");
1163 info->b_commiting = FALSE;
1164 ret = MM_ERROR_CAMCORDER_INTERNAL;
1165 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1168 _mmcam_dbg_log("No audio stream");
1172 sc->display_interval = 0;
1173 sc->previous_slot_time = 0;
1176 _mmcam_dbg_log("Start to wait EOS");
1177 ret = _mmcamcorder_get_eos_message(handle);
1178 if (ret != MM_ERROR_NONE) {
1179 info->b_commiting = FALSE;
1180 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1184 hcamcorder->capture_in_recording = FALSE;
1188 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1189 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1192 return MM_ERROR_NONE;
1194 _ERR_CAMCORDER_VIDEO_COMMAND:
1195 if (command == _MMCamcorder_CMD_RECORD)
1196 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1202 int _mmcamcorder_video_handle_eos(MMHandleType handle)
1204 int ret = MM_ERROR_NONE;
1206 guint64 file_size = 0;
1208 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1209 _MMCamcorderSubContext *sc = NULL;
1210 _MMCamcorderVideoInfo *info = NULL;
1211 _MMCamcorderMsgItem msg;
1212 MMCamRecordingReport *report = NULL;
1214 mmf_return_val_if_fail(hcamcorder, FALSE);
1216 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1217 mmf_return_val_if_fail(sc, FALSE);
1218 mmf_return_val_if_fail(sc->info_video, FALSE);
1220 info = sc->info_video;
1224 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1225 /* Play record stop sound */
1226 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1228 _mmcam_dbg_warn("Play stop sound through pulseaudio");
1230 _mmcamcorder_sound_init(handle);
1232 _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, TRUE);
1234 _mmcamcorder_sound_finalize(handle);
1237 /* remove blocking part */
1238 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1240 mm_camcorder_get_attributes(handle, NULL,
1241 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1244 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1245 if (ret != MM_ERROR_NONE)
1246 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1248 /* set recording hint */
1249 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1251 /* stop video stream */
1252 if (info->record_dual_stream) {
1253 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1255 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1257 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1258 gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1260 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1262 _mmcam_dbg_err("failed to get camera control");
1266 if (enabletag && !(sc->ferror_send)) {
1267 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1269 _mmcam_dbg_log("Writing location information SUCCEEDED !!");
1271 _mmcam_dbg_err("Writing location information FAILED !!");
1275 /* Check file size */
1276 if (info->max_size > 0) {
1277 _mmcamcorder_get_file_size(info->filename, &file_size);
1278 _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
1279 info->max_size, file_size);
1281 if (file_size > info->max_size) {
1282 _MMCamcorderMsgItem message;
1283 _mmcam_dbg_err("File size is greater than max size !!");
1284 message.id = MM_MESSAGE_CAMCORDER_ERROR;
1285 message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1286 _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1290 if (info->restart_preview) {
1292 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1293 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1294 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1296 _mmcam_dbg_log("Set state of pipeline as READY");
1297 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1299 /* check decoder recreation */
1300 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1301 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1302 ret = MM_ERROR_CAMCORDER_INTERNAL;
1306 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1307 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1308 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1310 if (ret != MM_ERROR_NONE) {
1311 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1312 msg.param.code = ret;
1313 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1314 _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1317 /* reset restart_preview for inset window layout */
1318 info->restart_preview = FALSE;
1320 /* recover preview size */
1321 _mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height);
1323 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1324 /* Do not return when error is occurred.
1325 Recording file was created successfully, but starting pipeline failed */
1326 if (ret != MM_ERROR_NONE) {
1327 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1328 msg.param.code = ret;
1329 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1330 _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1333 _mmcam_dbg_log("No need to restart preview");
1336 /* Send recording report to application */
1337 msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1338 report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1340 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1342 report->recording_filename = g_strdup(info->filename);
1343 msg.param.data = report;
1345 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1349 sc->pipeline_time = 0;
1351 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1352 sc->isMaxtimePausing = FALSE;
1353 hcamcorder->error_occurs = FALSE;
1355 info->video_frame_count = 0;
1356 info->audio_frame_count = 0;
1358 info->b_commiting = FALSE;
1360 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1361 /* check recording stop sound */
1362 _mmcamcorder_sound_solo_play_wait(handle);
1365 _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1371 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1373 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1374 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1376 _MMCamcorderSubContext *sc = NULL;
1377 _MMCamcorderVideoInfo *videoinfo = NULL;
1378 _MMCamcorderMsgItem msg;
1379 guint64 buffer_size = 0;
1380 guint64 trailer_size = 0;
1381 guint64 max_size = 0;
1383 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1384 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1385 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1387 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1388 videoinfo = sc->info_video;
1390 /* get buffer size */
1391 if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1392 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1393 return GST_PAD_PROBE_OK;
1396 buffer_size = mapinfo.size;
1397 gst_buffer_unmap(buffer, &mapinfo);
1399 /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1401 g_mutex_lock(&videoinfo->size_check_lock);
1403 if (videoinfo->audio_frame_count == 0) {
1404 videoinfo->filesize += buffer_size;
1405 videoinfo->audio_frame_count++;
1406 g_mutex_unlock(&videoinfo->size_check_lock);
1407 return GST_PAD_PROBE_OK;
1410 if (sc->ferror_send || sc->isMaxsizePausing) {
1411 _mmcam_dbg_warn("Recording is paused, drop frames");
1412 g_mutex_unlock(&videoinfo->size_check_lock);
1413 return GST_PAD_PROBE_DROP;
1416 /* get trailer size */
1417 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1418 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1423 /* check max size of recorded file */
1424 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1425 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1426 GstState pipeline_state = GST_STATE_VOID_PENDING;
1427 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1428 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1429 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1430 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1431 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1433 if (!sc->isMaxsizePausing) {
1434 sc->isMaxsizePausing = TRUE;
1435 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1436 if (pipeline_state == GST_STATE_PLAYING)
1437 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1439 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1440 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1443 g_mutex_unlock(&videoinfo->size_check_lock);
1448 videoinfo->filesize += buffer_size;
1449 videoinfo->audio_frame_count++;
1451 g_mutex_unlock(&videoinfo->size_check_lock);
1453 return GST_PAD_PROBE_OK;
1457 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1462 guint64 free_space = 0;
1463 guint64 buffer_size = 0;
1464 guint64 trailer_size = 0;
1465 guint64 queued_buffer = 0;
1466 guint64 max_size = 0;
1467 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1469 storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1471 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1472 _MMCamcorderMsgItem msg;
1473 _MMCamcorderSubContext *sc = NULL;
1474 _MMCamcorderVideoInfo *videoinfo = NULL;
1476 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1477 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1479 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1480 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1481 videoinfo = sc->info_video;
1483 /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1484 if (sc->ferror_send) {
1485 _mmcam_dbg_warn("file write error, drop frames");
1486 return GST_PAD_PROBE_DROP;
1489 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1490 buffer_size = mapinfo.size;
1491 gst_buffer_unmap(buffer, &mapinfo);
1493 videoinfo->video_frame_count++;
1494 if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1495 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1496 info->video_frame_count); */
1497 g_mutex_lock(&videoinfo->size_check_lock);
1498 videoinfo->filesize += buffer_size;
1499 g_mutex_unlock(&videoinfo->size_check_lock);
1500 return GST_PAD_PROBE_OK;
1503 /* get trailer size */
1504 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1505 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1510 /* check free space */
1511 ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1513 _mmcam_dbg_err("Error occured. [%d]", ret);
1514 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1515 sc->ferror_send = TRUE;
1517 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1518 msg.param.code = MM_ERROR_FILE_READ;
1520 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1525 return GST_PAD_PROBE_DROP; /* skip this buffer */
1528 if (free_space == 0) {
1529 /* check storage state */
1530 storage_get_state(hcamcorder->storage_info.id, &storage_state);
1532 _mmcam_dbg_warn("storage state %d", storage_state);
1534 if (storage_state == STORAGE_STATE_REMOVED ||
1535 storage_state == STORAGE_STATE_UNMOUNTABLE) {
1536 _mmcam_dbg_err("storage was removed!");
1538 _MMCAMCORDER_LOCK(hcamcorder);
1540 if (sc->ferror_send == FALSE) {
1541 _mmcam_dbg_err("OUT_OF_STORAGE error");
1543 sc->ferror_send = TRUE;
1545 _MMCAMCORDER_UNLOCK(hcamcorder);
1547 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1548 msg.param.code = MM_ERROR_OUT_OF_STORAGE;
1550 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1552 _MMCAMCORDER_UNLOCK(hcamcorder);
1553 _mmcam_dbg_warn("error was already sent");
1556 return GST_PAD_PROBE_DROP;
1560 /* get queued buffer size */
1561 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
1562 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
1565 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
1566 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1569 queued_buffer = aq_size + vq_size;
1571 if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1572 _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
1573 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
1574 " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
1575 free_space, trailer_size, buffer_size, queued_buffer);
1577 if (!sc->isMaxsizePausing) {
1578 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1579 sc->isMaxsizePausing = TRUE;
1581 msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
1582 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1585 return GST_PAD_PROBE_DROP;
1588 g_mutex_lock(&videoinfo->size_check_lock);
1590 /* check max size of recorded file */
1591 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1592 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1593 GstState pipeline_state = GST_STATE_VOID_PENDING;
1594 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1595 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1596 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1597 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1598 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1600 if (!sc->isMaxsizePausing) {
1601 sc->isMaxsizePausing = TRUE;
1602 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1603 if (pipeline_state == GST_STATE_PLAYING)
1604 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1606 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1607 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1610 g_mutex_unlock(&videoinfo->size_check_lock);
1612 return GST_PAD_PROBE_DROP;
1615 videoinfo->filesize += (guint64)buffer_size;
1618 _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
1621 g_mutex_unlock(&videoinfo->size_check_lock);
1623 return GST_PAD_PROBE_OK;
1627 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1629 guint64 trailer_size = 0;
1630 guint64 rec_pipe_time = 0;
1631 unsigned int remained_time = 0;
1633 GstClockTime b_time;
1635 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1636 _MMCamcorderMsgItem msg;
1637 _MMCamcorderSubContext *sc = NULL;
1638 _MMCamcorderVideoInfo *videoinfo = NULL;
1640 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1642 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1643 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1645 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1646 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1647 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1649 videoinfo = sc->info_video;
1651 b_time = GST_BUFFER_PTS(buffer);
1653 rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1655 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1656 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1661 /* check max time */
1662 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1663 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1664 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1666 if (!sc->isMaxtimePausing) {
1667 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1669 sc->isMaxtimePausing = TRUE;
1671 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1672 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1673 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1674 msg.param.recording_status.remained_time = 0;
1675 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1677 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1678 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1681 return GST_PAD_PROBE_DROP;
1684 /* calculate remained time can be recorded */
1685 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1686 remained_time = videoinfo->max_time - rec_pipe_time;
1687 } else if (videoinfo->max_size > 0) {
1688 long double max_size = (long double)videoinfo->max_size;
1689 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1691 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1694 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1695 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1696 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1697 msg.param.recording_status.remained_time = remained_time;
1698 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1701 _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1702 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1705 if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1706 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1709 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1710 record_motion_rate, videoinfo->record_drop_count);
1713 /* drop some frame if fast motion */
1714 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1715 if (record_motion_rate != (videoinfo->record_drop_count++)) {
1717 _mmcam_dbg_warn("drop frame");
1719 return GST_PAD_PROBE_DROP;
1722 videoinfo->record_drop_count = 1;
1724 _mmcam_dbg_warn("pass frame");
1728 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1729 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1732 return GST_PAD_PROBE_OK;
1736 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1738 _MMCamcorderMsgItem msg;
1739 guint64 trailer_size = 0;
1740 guint64 rec_pipe_time = 0;
1741 _MMCamcorderSubContext *sc = NULL;
1742 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1743 _MMCamcorderVideoInfo *videoinfo = NULL;
1744 unsigned int remained_time = 0;
1745 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1747 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1748 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1749 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1751 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1752 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1753 mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1755 videoinfo = sc->info_video;
1757 if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1758 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1759 return GST_PAD_PROBE_OK;
1762 rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1764 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1765 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1770 /* calculate remained time can be recorded */
1771 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1772 remained_time = videoinfo->max_time - rec_pipe_time;
1773 } else if (videoinfo->max_size > 0) {
1774 long double max_size = (long double)videoinfo->max_size;
1775 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1777 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1780 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1781 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1782 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1784 if (!sc->isMaxtimePausing) {
1785 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1787 sc->isMaxtimePausing = TRUE;
1789 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1790 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1791 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1792 msg.param.recording_status.remained_time = 0;
1793 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1795 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1796 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1799 return GST_PAD_PROBE_DROP;
1802 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1803 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1804 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1805 msg.param.recording_status.remained_time = remained_time;
1806 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1809 _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1810 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1813 return GST_PAD_PROBE_OK;
1817 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1819 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1820 double volume = 0.0;
1823 int err = MM_ERROR_UNKNOWN;
1824 char *err_name = NULL;
1825 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1828 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1829 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1831 /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1832 err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1833 MMCAM_AUDIO_VOLUME, &volume,
1834 MMCAM_AUDIO_FORMAT, &format,
1835 MMCAM_AUDIO_CHANNEL, &channel,
1837 if (err != MM_ERROR_NONE) {
1838 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1839 SAFE_FREE(err_name);
1843 memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1845 gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1847 /* Set audio stream NULL */
1849 memset(mapinfo.data, 0, mapinfo.size);
1851 /* CALL audio stream callback */
1852 if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1853 MMCamcorderAudioStreamDataType stream;
1855 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1856 _mmcam_dbg_warn("Not ready for stream callback");
1857 gst_buffer_unmap(buffer, &mapinfo);
1858 return GST_PAD_PROBE_OK;
1861 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1862 GST_BUFFER_DATA(buffer), width, height, format);*/
1864 stream.data = (void *)mapinfo.data;
1865 stream.format = format;
1866 stream.channel = channel;
1867 stream.length = mapinfo.size;
1868 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1870 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1872 if (hcamcorder->astream_cb)
1873 hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1875 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1878 gst_buffer_unmap(buffer, &mapinfo);
1879 return GST_PAD_PROBE_OK;
1883 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1885 gboolean bret = FALSE;
1887 switch (fileformat) {
1888 case MM_FILE_FORMAT_3GP:
1889 case MM_FILE_FORMAT_MP4:
1890 bret = __mmcamcorder_add_metadata_mp4(handle);
1893 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1901 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1905 guint64 udta_size = 0;
1906 gint64 current_pos = 0;
1907 gint64 moov_pos = 0;
1908 gint64 udta_pos = 0;
1909 gdouble longitude = 0;
1910 gdouble latitude = 0;
1911 gdouble altitude = 0;
1913 int orientation = 0;
1915 char *err_name = NULL;
1916 char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1917 _MMCamcorderLocationInfo location_info = {0, 0, 0};
1918 _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1920 _MMCamcorderVideoInfo *info = NULL;
1921 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1922 _MMCamcorderSubContext *sc = NULL;
1924 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1925 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1927 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1928 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1932 info = sc->info_video;
1934 f = fopen64(info->filename, "rb+");
1936 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1937 _mmcam_dbg_err("file open failed [%s]", err_msg);
1941 mm_camcorder_get_attributes(handle, &err_name,
1942 MMCAM_TAG_LATITUDE, &latitude,
1943 MMCAM_TAG_LONGITUDE, &longitude,
1944 MMCAM_TAG_ALTITUDE, &altitude,
1945 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1946 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1949 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1950 SAFE_FREE(err_name);
1953 location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1954 location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1955 location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1956 geo_info.longitude = longitude *10000;
1957 geo_info.latitude = latitude *10000;
1958 geo_info.altitude = altitude *10000;
1959 /* find udta container.
1960 if, there are udta container, write loci box after that
1961 else, make udta container and write loci box. */
1962 if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1965 _mmcam_dbg_log("find udta container");
1968 if (fseek(f, -8L, SEEK_CUR) != 0)
1971 udta_pos = ftello(f);
1975 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1977 _mmcam_dbg_log("recorded file fread %d", nread);
1979 udta_size = _mmcamcorder_get_container_size(buf);
1981 /* goto end of udta and write 'loci' box */
1982 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1986 if (!_mmcamcorder_write_loci(f, location_info)) {
1987 _mmcam_dbg_err("failed to write loci");
1991 if (!_mmcamcorder_write_geodata(f, geo_info)) {
1992 _mmcam_dbg_err("failed to write geodata");
1997 current_pos = ftello(f);
1998 if (current_pos < 0)
2001 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
2004 _mmcam_dbg_log("No udta container");
2005 if (fseek(f, 0, SEEK_END) != 0)
2008 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
2009 _mmcam_dbg_err("failed to write udta");
2014 /* find moov container.
2015 update moov container size. */
2016 if ((current_pos = ftello(f)) < 0)
2019 if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
2020 gint64 internal_pos = ftello(f);
2022 _mmcam_dbg_log("found moov container");
2023 if (fseek(f, -8L, SEEK_CUR) != 0)
2026 moov_pos = ftello(f);
2030 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
2033 /* add orientation info */
2034 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
2035 _mmcam_dbg_err("fseek failed : errno %d", errno);
2039 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
2040 _mmcam_dbg_err("failed to find [trak] tag");
2044 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
2045 _mmcam_dbg_err("failed to find [tkhd] tag");
2049 _mmcam_dbg_log("found [tkhd] tag");
2051 /* seek to start position of composition matrix */
2052 fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR);
2054 /* update composition matrix for orientation */
2055 _mmcamcorder_update_composition_matrix(f, orientation);
2057 _mmcam_dbg_err("No 'moov' container");
2069 _mmcam_dbg_err("ftell() returns negative value.");
2075 int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
2077 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2078 _MMCamcorderSubContext *sc = NULL;
2080 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2082 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2083 mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2085 /* check video source element */
2086 if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
2087 _mmcam_dbg_warn("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
2088 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
2089 _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
2090 G_CALLBACK(__mmcamcorder_video_stream_cb),
2092 return MM_ERROR_NONE;
2094 _mmcam_dbg_err("videosrc element is not created yet");
2095 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
2100 int _mmcamcorder_video_prepare_record(MMHandleType handle)
2102 int ret = MM_ERROR_NONE;
2104 _MMCamcorderVideoInfo *info = NULL;
2105 _MMCamcorderSubContext *sc = NULL;
2106 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2108 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2110 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2111 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2112 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2114 info = sc->info_video;
2116 _mmcam_dbg_warn("start");
2118 /* create encoding pipeline */
2119 ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2120 if (ret != MM_ERROR_NONE)
2121 goto _ERR_PREPARE_RECORD;
2123 if (info->filename == NULL) {
2124 char *temp_filename = NULL;
2127 mm_camcorder_get_attributes(handle, NULL,
2128 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2131 info->filename = g_strdup(temp_filename);
2133 if (!info->filename) {
2134 _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
2135 goto _ERR_PREPARE_RECORD;
2139 _mmcam_dbg_log("Record file name [%s]", info->filename);
2141 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2142 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2144 /* Adjust display FPS */
2145 sc->display_interval = 0;
2146 sc->previous_slot_time = 0;
2148 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2149 if (ret != MM_ERROR_NONE)
2150 goto _ERR_PREPARE_RECORD;
2152 _mmcam_dbg_warn("done");
2156 _ERR_PREPARE_RECORD:
2157 /* Remove recorder pipeline and recording file which size maybe zero */
2158 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2159 if (info && info->filename) {
2160 _mmcam_dbg_log("file delete(%s)", info->filename);
2161 unlink(info->filename);