4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jeongmo Yang <jm80.yang@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 /*=======================================================================================
24 =======================================================================================*/
25 #include <gst/video/cameracontrol.h>
26 #include <gst/app/gstappsrc.h>
27 #include "mm_camcorder_internal.h"
28 #include "mm_camcorder_videorec.h"
30 /*---------------------------------------------------------------------------------------
31 | GLOBAL VARIABLE DEFINITIONS for internal |
32 ---------------------------------------------------------------------------------------*/
33 #define _MMCAMCORDER_LOCATION_INFO /* for add gps information */
34 #define MAX_ERROR_MESSAGE_LEN 128
36 /*---------------------------------------------------------------------------------------
37 | LOCAL VARIABLE DEFINITIONS for internal |
38 ---------------------------------------------------------------------------------------*/
39 #define _MMCAMCORDER_MINIMUM_FRAME 5
40 #define _MMCAMCORDER_RETRIAL_COUNT 10
41 #define _MMCAMCORDER_FRAME_WAIT_TIME 200000 /* ms */
42 #define _OFFSET_COMPOSITION_MATRIX 40L
43 #define _GOP_GEN_INTERVAL 1000000000 /*nano seconds*/
44 #define _MMCAMCORDER_VIDEO_MINIMUM_SPACE (_MMCAMCORDER_MINIMUM_SPACE << 1) /* byte */
46 /*---------------------------------------------------------------------------------------
47 | LOCAL FUNCTION PROTOTYPES: |
48 ---------------------------------------------------------------------------------------*/
49 /* STATIC INTERNAL FUNCTION */
50 static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data);
51 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
52 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
53 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
54 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
55 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
56 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat);
57 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle);
59 /*=======================================================================================
60 | FUNCTION DEFINITIONS |
61 =======================================================================================*/
62 /*---------------------------------------------------------------------------------------
63 | GLOBAL FUNCTION DEFINITIONS: |
64 ---------------------------------------------------------------------------------------*/
65 static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
67 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
68 _MMCamcorderSubContext *sc = NULL;
70 GstBuffer *buffer = gst_sample_get_buffer(sample);
71 mmf_return_val_if_fail(buffer, FALSE);
72 mmf_return_val_if_fail(gst_buffer_n_memory(buffer), FALSE);
73 mmf_return_val_if_fail(hcamcorder, FALSE);
75 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
76 mmf_return_val_if_fail(sc, FALSE);
79 _mmcam_dbg_log("ENTER - push_encoding_buffer %d, buffer %p, MALLOCDATA %p, size %d",
80 sc->info_video->push_encoding_buffer, buffer, GST_BUFFER_MALLOCDATA(buffer), GST_BUFFER_SIZE(buffer));
83 /* push buffer in appsrc to encode */
84 if (sc->info_video->push_encoding_buffer == PUSH_ENCODING_BUFFER_RUN &&
85 sc->info_video->record_dual_stream &&
86 sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst) {
87 GstFlowReturn ret = 0;
88 GstClock *pipe_clock = NULL;
90 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst) {
91 if (sc->info_video->is_firstframe) {
92 sc->info_video->is_firstframe = FALSE;
93 pipe_clock = GST_ELEMENT_CLOCK(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst);
95 gst_object_ref(pipe_clock);
96 sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer) - (gst_clock_get_time(pipe_clock) - GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time);
97 gst_object_unref(pipe_clock);
101 if (sc->info_video->is_firstframe) {
102 sc->info_video->is_firstframe = FALSE;
103 sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer);
107 GST_BUFFER_PTS(buffer) = GST_BUFFER_PTS(buffer) - sc->info_video->base_video_ts;
108 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
110 ret = gst_app_src_push_buffer((GstAppSrc *)sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, buffer);
111 if (ret != GST_FLOW_OK && ret != GST_FLOW_FLUSHING) {
112 _mmcam_dbg_err("gst_app_src_push_buffer failed [0x%x]", ret);
113 gst_buffer_unref(buffer);
117 /*_mmcam_dbg_log("push buffer result : 0x%x", ret);*/
119 _mmcam_dbg_warn("unref video buffer immediately - push encoding buffer %d",
120 sc->info_video->push_encoding_buffer);
122 gst_buffer_unref(buffer);
130 int _mmcamcorder_create_recorder_pipeline(MMHandleType handle)
133 int err = MM_ERROR_NONE;
134 const char* gst_element_rsink_name = NULL;
137 GstPad *srcpad = NULL;
138 GstPad *sinkpad = NULL;
140 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
141 _MMCamcorderSubContext *sc = NULL;
143 type_element *RecordsinkElement = NULL;
145 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
147 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
148 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
149 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
151 _mmcam_dbg_warn("start");
153 err = _mmcamcorder_check_videocodec_fileformat_compatibility(handle);
154 if (err != MM_ERROR_NONE)
158 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
159 _mmcam_dbg_log("pipeline is exist so need to remove pipeline _MMCAMCORDER_ENCODE_MAIN_PIPE = %p",
160 sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
161 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
164 _MMCAMCORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
166 /* get audio disable */
167 mm_camcorder_get_attributes(handle, NULL,
168 MMCAM_AUDIO_DISABLE, &sc->audio_disable,
171 _mmcam_dbg_log("MMCAM_AUDIO_DISABLE %d, is_modified_rate %d",
172 sc->audio_disable, sc->is_modified_rate);
174 sc->audio_disable |= sc->is_modified_rate;
176 if (sc->audio_disable == FALSE) {
177 /* create audiosrc bin */
178 err = _mmcamcorder_create_audiosrc_bin((MMHandleType)hcamcorder);
179 if (err != MM_ERROR_NONE)
183 err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder, MM_CAMCORDER_ENCBIN_PROFILE_VIDEO);
184 if (err != MM_ERROR_NONE)
187 if (sc->audio_disable == FALSE) {
188 gst_bin_add(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
189 sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
192 /* add element and encodesink bin to encode main pipeline */
193 gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
194 sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst,
195 sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst,
196 sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
199 /* Link each element : appsrc - capsfilter - encodesink bin */
200 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "src");
201 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "sink");
202 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
204 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "src");
205 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
206 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
208 if (sc->audio_disable == FALSE) {
209 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
210 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
211 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
214 _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
215 CONFIGURE_CATEGORY_MAIN_RECORD,
218 _mmcamcorder_conf_get_value_element_name(RecordsinkElement, &gst_element_rsink_name);
220 /* set data probe function */
222 /* register message cb */
224 /* set data probe functions */
225 if (sc->audio_disable == FALSE) {
226 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "sink");
227 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
228 __mmcamcorder_audioque_dataprobe, hcamcorder);
229 gst_object_unref(sinkpad);
233 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
234 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
235 __mmcamcorder_audio_dataprobe_audio_mute, hcamcorder);
236 gst_object_unref(srcpad);
239 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
240 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "src");
241 MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
242 __mmcamcorder_eventprobe_monitor, hcamcorder);
243 gst_object_unref(srcpad);
248 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
249 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "src");
250 MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
251 __mmcamcorder_eventprobe_monitor, hcamcorder);
252 gst_object_unref(srcpad);
256 if (sc->audio_disable) {
257 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "sink");
258 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
259 __mmcamcorder_video_dataprobe_audio_disable, hcamcorder);
260 gst_object_unref(sinkpad);
264 if (!strcmp(gst_element_rsink_name, "filesink")) {
265 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
266 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
267 __mmcamcorder_video_dataprobe_record, hcamcorder);
268 gst_object_unref(srcpad);
271 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
272 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
273 __mmcamcorder_audio_dataprobe_check, hcamcorder);
274 gst_object_unref(srcpad);
278 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "sink");
279 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
280 __mmcamcorder_muxed_dataprobe, hcamcorder);
281 MMCAMCORDER_ADD_EVENT_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
282 __mmcamcorder_eventprobe_monitor, hcamcorder);
283 gst_object_unref(sinkpad);
286 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
288 /* register pipeline message callback */
289 hcamcorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder);
291 /* set sync handler */
292 gst_bus_set_sync_handler(bus, _mmcamcorder_encode_pipeline_bus_sync_callback, (gpointer)hcamcorder, NULL);
294 gst_object_unref(bus);
297 return MM_ERROR_NONE;
299 pipeline_creation_error:
300 for (i = _MMCAMCORDER_AUDIOSRC_BIN ; i <= _MMCAMCORDER_ENCSINK_SINK ; i++)
301 _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, i);
303 _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE);
308 int _mmcamcorder_remove_audio_pipeline(MMHandleType handle)
310 GstPad *srcpad = NULL;
311 GstPad *sinkpad = NULL;
312 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
313 _MMCamcorderSubContext *sc = NULL;
315 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
317 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
318 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
319 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
323 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst != NULL) {
324 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
325 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
326 _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
328 /* release audiosrc bin */
329 gst_bin_remove(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
330 sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
333 To avoid conflicting between old elements and newly created elements,
334 I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
335 This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
336 So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
337 It's because the pipeline of audio recording destroys at the same time,
338 and '_mmcamcorder_element_release_noti' will perfom removing handle.
340 _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element, _MMCAMCORDER_AUDIOSRC_BIN, _MMCAMCORDER_AUDIOSRC_VOL);
342 _mmcam_dbg_log("Audio pipeline removed");
345 return MM_ERROR_NONE;
349 int _mmcamcorder_remove_encode_pipeline(MMHandleType handle)
351 GstPad *reqpad = NULL;
352 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
353 _MMCamcorderSubContext *sc = NULL;
354 #ifdef _MMCAMCORDER_MURPHY_SUPPORT
355 int ret = MM_ERROR_NONE;
356 MMCamcorderResourceManager *resource_manager = NULL;
357 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
359 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
361 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
362 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
363 mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
367 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst != NULL) {
368 /* release request pad */
369 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
371 gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
372 gst_object_unref(reqpad);
376 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
378 gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
379 gst_object_unref(reqpad);
383 /* release encode main pipeline */
384 gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
387 To avoid conflicting between old elements and newly created elements,
388 I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
389 This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
390 So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
391 It's because the pipeline of audio recording destroys at the same time,
392 and '_mmcamcorder_element_release_noti' will perfom removing handle.
394 /* _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element,
395 _MMCAMCORDER_ENCODE_MAIN_PIPE, _MMCAMCORDER_ENCSINK_SINK); */
397 _mmcam_dbg_warn("Encoder pipeline removed");
399 #ifdef _MMCAMCORDER_MURPHY_SUPPORT
400 resource_manager = &hcamcorder->resource_manager_sub;
402 _mmcam_dbg_warn("lock resource - cb calling %d", resource_manager->is_release_cb_calling);
404 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
406 if (resource_manager->is_release_cb_calling == FALSE) {
407 /* release resource */
408 ret = _mmcamcorder_resource_manager_release(resource_manager);
410 _mmcam_dbg_warn("release resource 0x%x", ret);
412 if (resource_manager->acquire_remain < resource_manager->acquire_count) {
413 /* wait for resource release */
414 gint64 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
415 _mmcam_dbg_log("resource is not released all. wait for signal...");
416 _MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time);
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 && !hcamcorder->mstream_cb) {
626 _mmcam_dbg_err("filename is not set and muxed stream cb is NULL");
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");
680 (ret_free_space == -1 || free_space <= _MMCAMCORDER_VIDEO_MINIMUM_SPACE)) {
681 _mmcam_dbg_err("OUT of STORAGE [ret_free_space:%d or free space [%" G_GUINT64_FORMAT "] is smaller than [%d]",
682 ret_free_space, free_space, _MMCAMCORDER_VIDEO_MINIMUM_SPACE);
683 return MM_ERROR_OUT_OF_STORAGE;
686 g_mutex_lock(&hcamcorder->task_thread_lock);
687 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
688 hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
689 /* Play record start sound */
690 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_START, FALSE);
692 g_mutex_unlock(&hcamcorder->task_thread_lock);
694 _mmcam_dbg_warn("video size [%dx%d]", info->video_width, info->video_height);
696 if (info->video_width == 0 || info->video_height == 0) {
697 _mmcam_dbg_warn("video size is invalid [%dx%d] use preview size [%dx%d]",
698 info->video_width, info->video_height, info->preview_width, info->preview_height);
699 info->video_width = info->preview_width;
700 info->video_height = info->preview_height;
703 if (info->support_dual_stream) {
704 _mmcam_dbg_warn("DUAL STREAM MODE");
706 info->record_dual_stream = TRUE;
708 /* No need to restart preview */
709 info->restart_preview = FALSE;
711 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width);
712 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height);
713 } else if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
714 info->preview_width == info->video_width &&
715 info->preview_height == info->video_height) {
716 _mmcam_dbg_log("H264 preview mode and same resolution");
718 /* No need to restart preview */
719 info->restart_preview = FALSE;
721 /* always need to restart preview */
722 info->restart_preview = TRUE;
725 /* set recording hint */
726 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", TRUE);
728 if (info->restart_preview) {
729 /* stop preview and set new size */
730 _mmcam_dbg_log("restart preview");
732 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
733 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
734 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
736 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
738 /* check decoder recreation */
739 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
740 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
741 ret = MM_ERROR_CAMCORDER_INTERNAL;
742 goto _ERR_CAMCORDER_VIDEO_COMMAND;
745 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
746 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
747 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
749 if (ret != MM_ERROR_NONE)
750 goto _ERR_CAMCORDER_VIDEO_COMMAND;
752 if (!_mmcamcorder_set_camera_resolution(handle, info->video_width, info->video_height)) {
753 ret = MM_ERROR_CAMCORDER_INTERNAL;
754 goto _ERR_CAMCORDER_VIDEO_COMMAND;
757 /* Start preview again with new setting */
758 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
759 if (ret != MM_ERROR_NONE)
760 goto _ERR_CAMCORDER_VIDEO_COMMAND;
762 if (motion_rate < 1.0) {
763 _mmcam_dbg_warn("wait for stabilization of frame");
767 _mmcam_dbg_log("no need to restart preview");
770 _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
771 CONFIGURE_CATEGORY_MAIN_RECORD,
775 _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
776 CONFIGURE_CATEGORY_MAIN_RECORD,
777 "PassFirstVideoFrame",
778 &(sc->pass_first_vframe));
780 _mmcam_dbg_log("Drop video frame count[%d], Pass fisrt video frame count[%d]",
781 sc->drop_vframe, sc->pass_first_vframe);
783 info->record_drop_count = (guint)motion_rate;
784 info->record_motion_rate = motion_rate;
785 if (sc->is_modified_rate)
786 info->record_timestamp_ratio = (_MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE/motion_rate);
788 info->record_timestamp_ratio = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
790 _mmcam_dbg_warn("recording fps %d, motion rate %f, timestamp_ratio %f",
791 fps, info->record_motion_rate, info->record_timestamp_ratio);
793 /* set push buffer flag */
794 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT;
795 info->base_video_ts = 0;
797 /* connect video stream cb signal */
798 /*130826 Connect video stream cb for handling fast record frame cb*/
799 if (info->record_dual_stream) {
800 if (_mmcamcorder_connect_video_stream_cb_signal((MMHandleType)hcamcorder) != MM_ERROR_NONE)
801 goto _ERR_CAMCORDER_VIDEO_COMMAND;
804 /* start video stream */
805 if (info->record_dual_stream) {
806 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
808 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
810 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_START");
811 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_START);
813 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
815 _mmcam_dbg_err("could not get camera control");
819 /* check pre-created encode pipeline */
820 g_mutex_lock(&hcamcorder->task_thread_lock);
821 if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
822 hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
823 /* create encoding pipeline */
824 ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
825 if (ret != MM_ERROR_NONE) {
826 g_mutex_unlock(&hcamcorder->task_thread_lock);
827 goto _ERR_CAMCORDER_VIDEO_COMMAND;
830 g_mutex_unlock(&hcamcorder->task_thread_lock);
832 /* check recording start sound */
833 _mmcamcorder_sound_solo_play_wait(handle);
835 /**< To fix video recording hanging
836 1. use gst_element_set_start_time() instead of gst_pipeline_set_new_stream_time()
837 2. Set (GstClockTime)1 instead of (GstClockTime)0. Because of strict check in gstreamer 0.25,
838 basetime wouldn't change if you set (GstClockTime)0.
839 3. Move set start time position below PAUSED of pipeline.
842 gst_element_set_start_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), (GstClockTime)1);
843 gst_element_set_start_time(GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), (GstClockTime)1);
846 info->video_frame_count = 0;
847 info->is_firstframe = TRUE;
848 info->audio_frame_count = 0;
850 sc->ferror_send = FALSE;
851 sc->ferror_count = 0;
852 hcamcorder->error_occurs = FALSE;
853 sc->bget_eos = FALSE;
854 sc->muxed_stream_offset = 0;
856 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
857 if (ret != MM_ERROR_NONE) {
858 /* stop video stream */
859 if (info->record_dual_stream) {
860 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
862 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
864 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
865 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
867 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
869 _mmcam_dbg_err("failed to get camera control");
873 /* Remove recorder pipeline and recording file which size maybe zero */
874 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
875 if (info->filename) {
876 _mmcam_dbg_log("file delete(%s)", info->filename);
877 unlink(info->filename);
879 goto _ERR_CAMCORDER_VIDEO_COMMAND;
882 /*set the camera control to create the GOP so that video record will get a new key frame*/
883 if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
884 GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
885 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
886 controls = gst_camera_control_list_channels(CameraControl);
887 if (controls != NULL) {
888 for (item = controls ; item && item->data ; item = item->next) {
889 CameraControlChannel = item->data;
890 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
891 if (!strcmp(CameraControlChannel->label, "new-gop")) {
892 /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
898 _mmcam_dbg_warn("failed to find new-gop control channel");
901 _mmcam_dbg_warn("Can't cast Video source into camera control or not H264 prevew format[%d]",
902 sc->info_image->preview_format);
907 if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
908 GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
909 /* generate and I-frame on resuming */
910 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
911 controls = gst_camera_control_list_channels(CameraControl);
912 if (controls != NULL) {
913 for (item = controls ; item && item->data ; item = item->next) {
914 CameraControlChannel = item->data;
915 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
916 if (!strcmp(CameraControlChannel->label, "new-gop")) {
917 /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
923 _mmcam_dbg_warn("failed to find new-gop control channel");
927 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
929 _mmcam_dbg_log("Object property settings done");
933 case _MMCamcorder_CMD_PAUSE:
935 if (info->b_commiting) {
936 _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
937 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
940 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
941 if (sc->audio_disable) {
942 /* check only video frame */
943 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
945 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
946 _mmcam_dbg_err("Pause fail, frame count %llu", info->video_frame_count);
947 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
949 _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %llu", count, info->video_frame_count);
952 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
954 /* check both of video and audio frame */
955 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
957 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
958 _mmcam_dbg_err("Pause fail, frame count VIDEO[%llu], AUDIO [%llu]",
959 info->video_frame_count, info->audio_frame_count);
960 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
962 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu]",
963 count, info->video_frame_count, info->audio_frame_count);
966 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
970 /* block encodebin */
971 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
974 case _MMCamcorder_CMD_CANCEL:
976 if (info->b_commiting) {
977 _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
978 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
981 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
983 if (hcamcorder->capture_in_recording == FALSE) {
985 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
986 _mmcam_dbg_err("Failed to Wait capture data");
987 hcamcorder->capture_in_recording = FALSE;
990 _mmcam_dbg_warn("Waiting for capture data - retrial [%d]", count);
993 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
996 /* block push buffer */
997 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
999 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1000 if (ret != MM_ERROR_NONE)
1001 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1003 /* set recording hint */
1004 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1006 /* stop video stream */
1007 if (info->record_dual_stream) {
1008 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1009 if (CameraControl) {
1010 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1012 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1013 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1015 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1017 _mmcam_dbg_err("failed to get camera control");
1021 if (info->restart_preview) {
1022 /* restart preview */
1023 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1024 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1025 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1027 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
1029 /* check decoder recreation */
1030 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1031 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1032 ret = MM_ERROR_CAMCORDER_INTERNAL;
1035 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1036 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1037 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1039 if (ret != MM_ERROR_NONE)
1040 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1042 /* reset restart_preview for inset window layout */
1043 info->restart_preview = FALSE;
1045 if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1046 ret = MM_ERROR_CAMCORDER_INTERNAL;
1047 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1050 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
1051 if (ret != MM_ERROR_NONE)
1052 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1055 /* remove target file */
1056 if (info->filename) {
1057 _mmcam_dbg_log("file delete(%s)", info->filename);
1058 unlink(info->filename);
1061 sc->isMaxsizePausing = FALSE;
1062 sc->isMaxtimePausing = FALSE;
1064 sc->display_interval = 0;
1065 sc->previous_slot_time = 0;
1066 info->video_frame_count = 0;
1067 info->audio_frame_count = 0;
1069 hcamcorder->capture_in_recording = FALSE;
1072 case _MMCamcorder_CMD_COMMIT:
1076 if (info->b_commiting) {
1077 _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command);
1078 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
1080 _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
1081 info->b_commiting = TRUE;
1082 sc->bget_eos = FALSE;
1085 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
1086 if (sc->audio_disable) {
1087 /* check only video frame */
1088 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1089 hcamcorder->capture_in_recording == FALSE) {
1091 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1092 _mmcam_dbg_err("Commit fail, frame count is %llu, capturing %d",
1093 info->video_frame_count, hcamcorder->capture_in_recording);
1095 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
1096 _mmcam_dbg_warn("video frames are enough. keep going...");
1098 info->b_commiting = FALSE;
1099 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1102 _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %llu, capturing %d",
1103 count, info->video_frame_count, hcamcorder->capture_in_recording);
1106 /* check both of video and audio frame */
1107 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1108 info->audio_frame_count &&
1109 hcamcorder->capture_in_recording == FALSE) {
1111 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1112 _mmcam_dbg_err("Commit fail, VIDEO[%llu], AUDIO [%llu], capturing %d",
1113 info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1115 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
1116 _mmcam_dbg_warn("video/audio frames are enough. keep going...");
1118 info->b_commiting = FALSE;
1119 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1122 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1124 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu], capturing %d",
1125 count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1129 if (hcamcorder->capture_in_recording) {
1130 gint64 end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND);
1131 if (!_MMCAMCORDER_CMD_WAIT_UNTIL(handle, end_time))
1132 _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 _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1143 if (free_space < _MMCAMCORDER_MINIMUM_SPACE) {
1144 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT out of storage [%" G_GUINT64_FORMAT "]", free_space);
1145 ret = MM_ERROR_OUT_OF_STORAGE;
1146 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1149 if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
1150 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
1151 _mmcam_dbg_warn("VIDEO: send eos to appsrc done");
1153 _mmcam_dbg_err("VIDEO: send EOS failed");
1154 info->b_commiting = FALSE;
1155 ret = MM_ERROR_CAMCORDER_INTERNAL;
1156 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1159 _mmcam_dbg_err("No video stream source");
1160 info->b_commiting = FALSE;
1161 ret = MM_ERROR_CAMCORDER_INTERNAL;
1162 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1165 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
1166 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
1167 _mmcam_dbg_warn("AUDIO: send eos to audiosrc done");
1169 _mmcam_dbg_err("AUDIO: send EOS failed");
1170 info->b_commiting = FALSE;
1171 ret = MM_ERROR_CAMCORDER_INTERNAL;
1172 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1175 _mmcam_dbg_log("No audio stream");
1179 sc->display_interval = 0;
1180 sc->previous_slot_time = 0;
1183 _mmcam_dbg_log("Start to wait EOS");
1184 ret = _mmcamcorder_get_eos_message(handle);
1185 if (ret != MM_ERROR_NONE) {
1186 info->b_commiting = FALSE;
1187 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1191 hcamcorder->capture_in_recording = FALSE;
1195 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1196 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1199 return MM_ERROR_NONE;
1201 _ERR_CAMCORDER_VIDEO_COMMAND:
1202 if (command == _MMCamcorder_CMD_RECORD)
1203 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1209 int _mmcamcorder_video_handle_eos(MMHandleType handle)
1211 int ret = MM_ERROR_NONE;
1213 guint64 file_size = 0;
1215 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1216 _MMCamcorderSubContext *sc = NULL;
1217 _MMCamcorderVideoInfo *info = NULL;
1218 _MMCamcorderMsgItem msg;
1219 MMCamRecordingReport *report = NULL;
1221 mmf_return_val_if_fail(hcamcorder, FALSE);
1223 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1224 mmf_return_val_if_fail(sc, FALSE);
1225 mmf_return_val_if_fail(sc->info_video, FALSE);
1227 info = sc->info_video;
1231 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1232 /* Play record stop sound */
1233 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1235 _mmcam_dbg_warn("Play stop sound through pulseaudio");
1237 _mmcamcorder_sound_init(handle);
1239 _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, TRUE);
1241 _mmcamcorder_sound_finalize(handle);
1244 /* remove blocking part */
1245 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1247 mm_camcorder_get_attributes(handle, NULL,
1248 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1251 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1252 if (ret != MM_ERROR_NONE)
1253 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1255 /* set recording hint */
1256 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1258 /* stop video stream */
1259 if (info->record_dual_stream) {
1260 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1262 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1264 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1265 gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1267 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1269 _mmcam_dbg_err("failed to get camera control");
1273 if (enabletag && !(sc->ferror_send)) {
1274 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1275 _mmcam_dbg_log("Writing location information [%s] !!", ret ? "SUCCEEDED" : "FAILED");
1278 /* Check file size */
1279 if (info->max_size > 0) {
1280 _mmcamcorder_get_file_size(info->filename, &file_size);
1281 _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
1282 info->max_size, file_size);
1284 if (file_size > info->max_size) {
1285 _MMCamcorderMsgItem message;
1286 _mmcam_dbg_err("File size is greater than max size !!");
1287 message.id = MM_MESSAGE_CAMCORDER_ERROR;
1288 message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1289 _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1293 if (info->restart_preview) {
1295 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1296 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1297 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1299 _mmcam_dbg_log("Set state of pipeline as READY");
1300 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1302 /* check decoder recreation */
1303 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1304 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1305 ret = MM_ERROR_CAMCORDER_INTERNAL;
1309 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1310 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1311 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1313 if (ret != MM_ERROR_NONE) {
1314 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1315 msg.param.code = ret;
1316 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1317 _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1320 /* reset restart_preview for inset window layout */
1321 info->restart_preview = FALSE;
1323 /* recover preview size */
1324 _mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height);
1326 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1327 /* Do not return when error is occurred.
1328 Recording file was created successfully, but starting pipeline failed */
1329 if (ret != MM_ERROR_NONE) {
1330 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1331 msg.param.code = ret;
1332 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1333 _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1336 _mmcam_dbg_log("No need to restart preview");
1339 /* Send recording report to application */
1340 msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1341 report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1343 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1345 report->recording_filename = g_strdup(info->filename);
1346 msg.param.data = report;
1348 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1352 sc->pipeline_time = 0;
1354 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1355 sc->isMaxtimePausing = FALSE;
1356 hcamcorder->error_occurs = FALSE;
1358 info->video_frame_count = 0;
1359 info->audio_frame_count = 0;
1361 info->b_commiting = FALSE;
1363 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1364 /* check recording stop sound */
1365 _mmcamcorder_sound_solo_play_wait(handle);
1368 _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1374 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1376 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1377 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1379 _MMCamcorderSubContext *sc = NULL;
1380 _MMCamcorderVideoInfo *videoinfo = NULL;
1381 _MMCamcorderMsgItem msg;
1382 guint64 buffer_size = 0;
1383 guint64 trailer_size = 0;
1384 guint64 max_size = 0;
1386 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1387 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1388 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1390 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1391 videoinfo = sc->info_video;
1393 /* get buffer size */
1394 if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1395 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1396 return GST_PAD_PROBE_OK;
1399 buffer_size = mapinfo.size;
1400 gst_buffer_unmap(buffer, &mapinfo);
1402 /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1404 g_mutex_lock(&videoinfo->size_check_lock);
1406 if (videoinfo->audio_frame_count == 0) {
1407 videoinfo->filesize += buffer_size;
1408 videoinfo->audio_frame_count++;
1409 g_mutex_unlock(&videoinfo->size_check_lock);
1410 return GST_PAD_PROBE_OK;
1413 if (sc->ferror_send || sc->isMaxsizePausing) {
1414 _mmcam_dbg_warn("Recording is paused, drop frames");
1415 g_mutex_unlock(&videoinfo->size_check_lock);
1416 return GST_PAD_PROBE_DROP;
1419 /* get trailer size */
1420 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1421 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1425 /* check max size of recorded file */
1426 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1427 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1428 GstState pipeline_state = GST_STATE_VOID_PENDING;
1429 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1430 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1431 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1432 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1433 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1435 if (!sc->isMaxsizePausing) {
1436 sc->isMaxsizePausing = TRUE;
1437 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1438 if (pipeline_state == GST_STATE_PLAYING)
1439 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1441 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1442 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1445 g_mutex_unlock(&videoinfo->size_check_lock);
1450 videoinfo->filesize += buffer_size;
1451 videoinfo->audio_frame_count++;
1453 g_mutex_unlock(&videoinfo->size_check_lock);
1455 return GST_PAD_PROBE_OK;
1459 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1464 guint64 free_space = 0;
1465 guint64 buffer_size = 0;
1466 guint64 trailer_size = 0;
1467 guint64 queued_buffer = 0;
1468 guint64 max_size = 0;
1469 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1471 storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1473 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1474 _MMCamcorderMsgItem msg;
1475 _MMCamcorderSubContext *sc = NULL;
1476 _MMCamcorderVideoInfo *videoinfo = NULL;
1478 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1479 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1481 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1482 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1483 videoinfo = sc->info_video;
1485 /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1486 if (sc->ferror_send) {
1487 _mmcam_dbg_warn("file write error, drop frames");
1488 return GST_PAD_PROBE_DROP;
1491 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1492 buffer_size = mapinfo.size;
1493 gst_buffer_unmap(buffer, &mapinfo);
1495 videoinfo->video_frame_count++;
1496 if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1497 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1498 info->video_frame_count); */
1499 g_mutex_lock(&videoinfo->size_check_lock);
1500 videoinfo->filesize += buffer_size;
1501 g_mutex_unlock(&videoinfo->size_check_lock);
1502 return GST_PAD_PROBE_OK;
1505 /* get trailer size */
1506 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1507 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1511 /* check free space */
1512 ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1514 _mmcam_dbg_err("Error occured. [%d]", ret);
1515 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1516 sc->ferror_send = TRUE;
1518 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1519 msg.param.code = MM_ERROR_FILE_READ;
1521 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1526 return GST_PAD_PROBE_DROP; /* skip this buffer */
1529 if (free_space == 0) {
1530 /* check storage state */
1531 storage_get_state(hcamcorder->storage_info.id, &storage_state);
1533 _mmcam_dbg_warn("storage state %d", storage_state);
1535 if (storage_state == STORAGE_STATE_REMOVED ||
1536 storage_state == STORAGE_STATE_UNMOUNTABLE) {
1537 _mmcam_dbg_err("storage was removed!");
1539 _MMCAMCORDER_LOCK(hcamcorder);
1541 if (sc->ferror_send == FALSE) {
1542 _mmcam_dbg_err("OUT_OF_STORAGE error");
1544 sc->ferror_send = TRUE;
1546 _MMCAMCORDER_UNLOCK(hcamcorder);
1548 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1549 msg.param.code = MM_ERROR_OUT_OF_STORAGE;
1551 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1553 _MMCAMCORDER_UNLOCK(hcamcorder);
1554 _mmcam_dbg_warn("error was already sent");
1557 return GST_PAD_PROBE_DROP;
1561 /* get queued buffer size */
1562 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst)
1563 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);
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);
1659 /* check max time */
1660 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1661 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1662 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1664 if (!sc->isMaxtimePausing) {
1665 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1667 sc->isMaxtimePausing = TRUE;
1669 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1670 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1671 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1672 msg.param.recording_status.remained_time = 0;
1673 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1675 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1676 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1679 return GST_PAD_PROBE_DROP;
1682 /* calculate remained time can be recorded */
1683 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1684 remained_time = videoinfo->max_time - rec_pipe_time;
1685 } else if (videoinfo->max_size > 0) {
1686 long double max_size = (long double)videoinfo->max_size;
1687 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1689 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1692 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1693 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1694 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1695 msg.param.recording_status.remained_time = remained_time;
1696 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1699 _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1700 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1703 if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1704 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1707 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1708 record_motion_rate, videoinfo->record_drop_count);
1711 /* drop some frame if fast motion */
1712 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1713 if (record_motion_rate != (videoinfo->record_drop_count++)) {
1715 _mmcam_dbg_warn("drop frame");
1717 return GST_PAD_PROBE_DROP;
1720 videoinfo->record_drop_count = 1;
1722 _mmcam_dbg_warn("pass frame");
1726 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1727 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1730 return GST_PAD_PROBE_OK;
1734 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1736 _MMCamcorderMsgItem msg;
1737 guint64 trailer_size = 0;
1738 guint64 rec_pipe_time = 0;
1739 _MMCamcorderSubContext *sc = NULL;
1740 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1741 _MMCamcorderVideoInfo *videoinfo = NULL;
1742 unsigned int remained_time = 0;
1743 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1745 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1746 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1747 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1749 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1750 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1751 mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1753 videoinfo = sc->info_video;
1755 if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1756 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1757 return GST_PAD_PROBE_OK;
1760 rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1762 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1763 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1767 /* calculate remained time can be recorded */
1768 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1769 remained_time = videoinfo->max_time - rec_pipe_time;
1770 } else if (videoinfo->max_size > 0) {
1771 long double max_size = (long double)videoinfo->max_size;
1772 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1774 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1777 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1778 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1779 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1781 if (!sc->isMaxtimePausing) {
1782 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1784 sc->isMaxtimePausing = TRUE;
1786 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1787 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1788 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1789 msg.param.recording_status.remained_time = 0;
1790 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1792 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1793 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1796 return GST_PAD_PROBE_DROP;
1799 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1800 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1801 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1802 msg.param.recording_status.remained_time = remained_time;
1803 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1806 _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1807 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1810 return GST_PAD_PROBE_OK;
1814 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1816 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1817 double volume = 0.0;
1820 int err = MM_ERROR_UNKNOWN;
1821 char *err_name = NULL;
1822 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1825 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1826 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1828 /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1829 err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1830 MMCAM_AUDIO_VOLUME, &volume,
1831 MMCAM_AUDIO_FORMAT, &format,
1832 MMCAM_AUDIO_CHANNEL, &channel,
1834 if (err != MM_ERROR_NONE) {
1835 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1836 SAFE_FREE(err_name);
1840 memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1842 gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1844 /* Set audio stream NULL */
1846 memset(mapinfo.data, 0, mapinfo.size);
1848 /* CALL audio stream callback */
1849 if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1850 MMCamcorderAudioStreamDataType stream;
1852 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1853 _mmcam_dbg_warn("Not ready for stream callback");
1854 gst_buffer_unmap(buffer, &mapinfo);
1855 return GST_PAD_PROBE_OK;
1858 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1859 GST_BUFFER_DATA(buffer), width, height, format);*/
1861 stream.data = (void *)mapinfo.data;
1862 stream.format = format;
1863 stream.channel = channel;
1864 stream.length = mapinfo.size;
1865 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1867 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1869 if (hcamcorder->astream_cb)
1870 hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1872 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1875 gst_buffer_unmap(buffer, &mapinfo);
1876 return GST_PAD_PROBE_OK;
1880 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1882 gboolean bret = FALSE;
1884 switch (fileformat) {
1885 case MM_FILE_FORMAT_3GP:
1886 case MM_FILE_FORMAT_MP4:
1887 bret = __mmcamcorder_add_metadata_mp4(handle);
1890 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1898 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1902 guint64 udta_size = 0;
1903 gint64 current_pos = 0;
1904 gint64 moov_pos = 0;
1905 gint64 udta_pos = 0;
1906 gdouble longitude = 0;
1907 gdouble latitude = 0;
1908 gdouble altitude = 0;
1910 int orientation = 0;
1912 char *err_name = NULL;
1913 char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1914 _MMCamcorderLocationInfo location_info = {0, 0, 0};
1915 _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1917 _MMCamcorderVideoInfo *info = NULL;
1918 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1919 _MMCamcorderSubContext *sc = NULL;
1921 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1922 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1924 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1925 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1929 info = sc->info_video;
1931 f = fopen64(info->filename, "rb+");
1933 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1934 _mmcam_dbg_err("file open failed [%s]", err_msg);
1938 mm_camcorder_get_attributes(handle, &err_name,
1939 MMCAM_TAG_LATITUDE, &latitude,
1940 MMCAM_TAG_LONGITUDE, &longitude,
1941 MMCAM_TAG_ALTITUDE, &altitude,
1942 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1943 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1946 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1947 SAFE_FREE(err_name);
1950 location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1951 location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1952 location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1953 geo_info.longitude = longitude *10000;
1954 geo_info.latitude = latitude *10000;
1955 geo_info.altitude = altitude *10000;
1956 /* find udta container.
1957 if, there are udta container, write loci box after that
1958 else, make udta container and write loci box. */
1959 if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1962 _mmcam_dbg_log("find udta container");
1965 if (fseek(f, -8L, SEEK_CUR) != 0)
1968 udta_pos = ftello(f);
1972 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1974 _mmcam_dbg_log("recorded file fread %d", nread);
1976 udta_size = _mmcamcorder_get_container_size(buf);
1978 /* goto end of udta and write 'loci' box */
1979 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1983 if (!_mmcamcorder_write_loci(f, location_info)) {
1984 _mmcam_dbg_err("failed to write loci");
1988 if (!_mmcamcorder_write_geodata(f, geo_info)) {
1989 _mmcam_dbg_err("failed to write geodata");
1994 current_pos = ftello(f);
1995 if (current_pos < 0)
1998 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
2001 _mmcam_dbg_log("No udta container");
2002 if (fseek(f, 0, SEEK_END) != 0)
2005 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
2006 _mmcam_dbg_err("failed to write udta");
2011 /* find moov container.
2012 update moov container size. */
2013 if ((current_pos = ftello(f)) < 0)
2016 if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
2017 gint64 internal_pos = ftello(f);
2019 _mmcam_dbg_log("found moov container");
2020 if (fseek(f, -8L, SEEK_CUR) != 0)
2023 moov_pos = ftello(f);
2027 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
2030 /* add orientation info */
2031 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
2032 _mmcam_dbg_err("fseeko failed : errno %d", errno);
2036 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
2037 _mmcam_dbg_err("failed to find [trak] tag");
2041 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
2042 _mmcam_dbg_err("failed to find [tkhd] tag");
2046 _mmcam_dbg_log("found [tkhd] tag");
2048 /* seek to start position of composition matrix */
2049 if (fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR) == 0) {
2050 /* update composition matrix for orientation */
2051 _mmcamcorder_update_composition_matrix(f, orientation);
2053 _mmcam_dbg_err("fseek failed : errno %d", errno);
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 char *temp_filename = NULL;
2106 _MMCamcorderVideoInfo *info = NULL;
2107 _MMCamcorderSubContext *sc = NULL;
2108 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2110 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2112 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2113 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2114 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2116 info = sc->info_video;
2118 _mmcam_dbg_warn("start");
2120 /* create encoding pipeline */
2121 ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2122 if (ret != MM_ERROR_NONE)
2123 goto _ERR_PREPARE_RECORD;
2125 SAFE_G_FREE(info->filename);
2127 mm_camcorder_get_attributes(handle, NULL,
2128 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2130 if (temp_filename) {
2131 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;
2137 _mmcam_dbg_log("Record file name [%s]", info->filename);
2138 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2140 _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
2141 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
2144 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2146 /* Adjust display FPS */
2147 sc->display_interval = 0;
2148 sc->previous_slot_time = 0;
2150 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2151 if (ret != MM_ERROR_NONE)
2152 goto _ERR_PREPARE_RECORD;
2154 _mmcam_dbg_warn("done");
2158 _ERR_PREPARE_RECORD:
2159 /* Remove recorder pipeline and recording file which size maybe zero */
2160 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2161 if (info && info->filename) {
2162 _mmcam_dbg_log("file delete(%s)", info->filename);
2163 unlink(info->filename);