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("signal received");
1134 _mmcam_dbg_warn("timeout");
1137 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
1141 /* block push buffer */
1142 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1143 _mmcam_dbg_log("block push buffer to appsrc");
1145 _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1146 if (free_space < _MMCAMCORDER_MINIMUM_SPACE) {
1147 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT out of storage [%" G_GUINT64_FORMAT "]", free_space);
1148 ret = MM_ERROR_OUT_OF_STORAGE;
1149 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1152 if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
1153 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
1154 _mmcam_dbg_warn("VIDEO: send eos to appsrc done");
1156 _mmcam_dbg_err("VIDEO: send EOS failed");
1157 info->b_commiting = FALSE;
1158 ret = MM_ERROR_CAMCORDER_INTERNAL;
1159 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1162 _mmcam_dbg_err("No video stream source");
1163 info->b_commiting = FALSE;
1164 ret = MM_ERROR_CAMCORDER_INTERNAL;
1165 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1168 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
1169 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
1170 _mmcam_dbg_warn("AUDIO: send eos to audiosrc done");
1172 _mmcam_dbg_err("AUDIO: send EOS failed");
1173 info->b_commiting = FALSE;
1174 ret = MM_ERROR_CAMCORDER_INTERNAL;
1175 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1178 _mmcam_dbg_log("No audio stream");
1182 sc->display_interval = 0;
1183 sc->previous_slot_time = 0;
1186 _mmcam_dbg_log("Start to wait EOS");
1187 ret = _mmcamcorder_get_eos_message(handle);
1188 if (ret != MM_ERROR_NONE) {
1189 info->b_commiting = FALSE;
1190 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1194 hcamcorder->capture_in_recording = FALSE;
1198 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1199 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1202 return MM_ERROR_NONE;
1204 _ERR_CAMCORDER_VIDEO_COMMAND:
1205 if (command == _MMCamcorder_CMD_RECORD)
1206 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1212 int _mmcamcorder_video_handle_eos(MMHandleType handle)
1214 int ret = MM_ERROR_NONE;
1216 guint64 file_size = 0;
1218 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1219 _MMCamcorderSubContext *sc = NULL;
1220 _MMCamcorderVideoInfo *info = NULL;
1221 _MMCamcorderMsgItem msg;
1222 MMCamRecordingReport *report = NULL;
1224 mmf_return_val_if_fail(hcamcorder, FALSE);
1226 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1227 mmf_return_val_if_fail(sc, FALSE);
1228 mmf_return_val_if_fail(sc->info_video, FALSE);
1230 info = sc->info_video;
1234 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1235 /* Play record stop sound */
1236 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1238 _mmcam_dbg_warn("Play stop sound through pulseaudio");
1240 _mmcamcorder_sound_init(handle);
1242 _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, TRUE);
1244 _mmcamcorder_sound_finalize(handle);
1247 /* remove blocking part */
1248 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1250 mm_camcorder_get_attributes(handle, NULL,
1251 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1254 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1255 if (ret != MM_ERROR_NONE)
1256 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1258 /* set recording hint */
1259 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1261 /* stop video stream */
1262 if (info->record_dual_stream) {
1263 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1265 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1267 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1268 gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1270 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1272 _mmcam_dbg_err("failed to get camera control");
1276 if (enabletag && !(sc->ferror_send)) {
1277 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1279 _mmcam_dbg_log("Writing location information SUCCEEDED !!");
1281 _mmcam_dbg_err("Writing location information FAILED !!");
1285 /* Check file size */
1286 if (info->max_size > 0) {
1287 _mmcamcorder_get_file_size(info->filename, &file_size);
1288 _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
1289 info->max_size, file_size);
1291 if (file_size > info->max_size) {
1292 _MMCamcorderMsgItem message;
1293 _mmcam_dbg_err("File size is greater than max size !!");
1294 message.id = MM_MESSAGE_CAMCORDER_ERROR;
1295 message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1296 _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1300 if (info->restart_preview) {
1302 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1303 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1304 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1306 _mmcam_dbg_log("Set state of pipeline as READY");
1307 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1309 /* check decoder recreation */
1310 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1311 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1312 ret = MM_ERROR_CAMCORDER_INTERNAL;
1316 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1317 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1318 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1320 if (ret != MM_ERROR_NONE) {
1321 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1322 msg.param.code = ret;
1323 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1324 _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1327 /* reset restart_preview for inset window layout */
1328 info->restart_preview = FALSE;
1330 /* recover preview size */
1331 _mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height);
1333 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1334 /* Do not return when error is occurred.
1335 Recording file was created successfully, but starting pipeline failed */
1336 if (ret != MM_ERROR_NONE) {
1337 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1338 msg.param.code = ret;
1339 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1340 _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1343 _mmcam_dbg_log("No need to restart preview");
1346 /* Send recording report to application */
1347 msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1348 report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1350 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1352 report->recording_filename = g_strdup(info->filename);
1353 msg.param.data = report;
1355 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1359 sc->pipeline_time = 0;
1361 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1362 sc->isMaxtimePausing = FALSE;
1363 hcamcorder->error_occurs = FALSE;
1365 info->video_frame_count = 0;
1366 info->audio_frame_count = 0;
1368 info->b_commiting = FALSE;
1370 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1371 /* check recording stop sound */
1372 _mmcamcorder_sound_solo_play_wait(handle);
1375 _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1381 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1383 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1384 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1386 _MMCamcorderSubContext *sc = NULL;
1387 _MMCamcorderVideoInfo *videoinfo = NULL;
1388 _MMCamcorderMsgItem msg;
1389 guint64 buffer_size = 0;
1390 guint64 trailer_size = 0;
1391 guint64 max_size = 0;
1393 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1394 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1395 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1397 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1398 videoinfo = sc->info_video;
1400 /* get buffer size */
1401 if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1402 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1403 return GST_PAD_PROBE_OK;
1406 buffer_size = mapinfo.size;
1407 gst_buffer_unmap(buffer, &mapinfo);
1409 /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1411 g_mutex_lock(&videoinfo->size_check_lock);
1413 if (videoinfo->audio_frame_count == 0) {
1414 videoinfo->filesize += buffer_size;
1415 videoinfo->audio_frame_count++;
1416 g_mutex_unlock(&videoinfo->size_check_lock);
1417 return GST_PAD_PROBE_OK;
1420 if (sc->ferror_send || sc->isMaxsizePausing) {
1421 _mmcam_dbg_warn("Recording is paused, drop frames");
1422 g_mutex_unlock(&videoinfo->size_check_lock);
1423 return GST_PAD_PROBE_DROP;
1426 /* get trailer size */
1427 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1428 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1433 /* check max size of recorded file */
1434 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1435 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1436 GstState pipeline_state = GST_STATE_VOID_PENDING;
1437 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1438 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1439 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1440 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1441 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1443 if (!sc->isMaxsizePausing) {
1444 sc->isMaxsizePausing = TRUE;
1445 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1446 if (pipeline_state == GST_STATE_PLAYING)
1447 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1449 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1450 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1453 g_mutex_unlock(&videoinfo->size_check_lock);
1458 videoinfo->filesize += buffer_size;
1459 videoinfo->audio_frame_count++;
1461 g_mutex_unlock(&videoinfo->size_check_lock);
1463 return GST_PAD_PROBE_OK;
1467 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1472 guint64 free_space = 0;
1473 guint64 buffer_size = 0;
1474 guint64 trailer_size = 0;
1475 guint64 queued_buffer = 0;
1476 guint64 max_size = 0;
1477 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1479 storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1481 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1482 _MMCamcorderMsgItem msg;
1483 _MMCamcorderSubContext *sc = NULL;
1484 _MMCamcorderVideoInfo *videoinfo = NULL;
1486 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1487 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1489 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1490 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1491 videoinfo = sc->info_video;
1493 /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1494 if (sc->ferror_send) {
1495 _mmcam_dbg_warn("file write error, drop frames");
1496 return GST_PAD_PROBE_DROP;
1499 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1500 buffer_size = mapinfo.size;
1501 gst_buffer_unmap(buffer, &mapinfo);
1503 videoinfo->video_frame_count++;
1504 if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1505 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1506 info->video_frame_count); */
1507 g_mutex_lock(&videoinfo->size_check_lock);
1508 videoinfo->filesize += buffer_size;
1509 g_mutex_unlock(&videoinfo->size_check_lock);
1510 return GST_PAD_PROBE_OK;
1513 /* get trailer size */
1514 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1515 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1520 /* check free space */
1521 ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1523 _mmcam_dbg_err("Error occured. [%d]", ret);
1524 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1525 sc->ferror_send = TRUE;
1527 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1528 msg.param.code = MM_ERROR_FILE_READ;
1530 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1535 return GST_PAD_PROBE_DROP; /* skip this buffer */
1538 if (free_space == 0) {
1539 /* check storage state */
1540 storage_get_state(hcamcorder->storage_info.id, &storage_state);
1542 _mmcam_dbg_warn("storage state %d", storage_state);
1544 if (storage_state == STORAGE_STATE_REMOVED ||
1545 storage_state == STORAGE_STATE_UNMOUNTABLE) {
1546 _mmcam_dbg_err("storage was removed!");
1548 _MMCAMCORDER_LOCK(hcamcorder);
1550 if (sc->ferror_send == FALSE) {
1551 _mmcam_dbg_err("OUT_OF_STORAGE error");
1553 sc->ferror_send = TRUE;
1555 _MMCAMCORDER_UNLOCK(hcamcorder);
1557 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1558 msg.param.code = MM_ERROR_OUT_OF_STORAGE;
1560 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1562 _MMCAMCORDER_UNLOCK(hcamcorder);
1563 _mmcam_dbg_warn("error was already sent");
1566 return GST_PAD_PROBE_DROP;
1570 /* get queued buffer size */
1571 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
1572 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
1575 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
1576 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1579 queued_buffer = aq_size + vq_size;
1581 if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1582 _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
1583 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
1584 " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
1585 free_space, trailer_size, buffer_size, queued_buffer);
1587 if (!sc->isMaxsizePausing) {
1588 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1589 sc->isMaxsizePausing = TRUE;
1591 msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
1592 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1595 return GST_PAD_PROBE_DROP;
1598 g_mutex_lock(&videoinfo->size_check_lock);
1600 /* check max size of recorded file */
1601 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1602 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1603 GstState pipeline_state = GST_STATE_VOID_PENDING;
1604 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1605 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1606 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1607 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1608 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1610 if (!sc->isMaxsizePausing) {
1611 sc->isMaxsizePausing = TRUE;
1612 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1613 if (pipeline_state == GST_STATE_PLAYING)
1614 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1616 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1617 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1620 g_mutex_unlock(&videoinfo->size_check_lock);
1622 return GST_PAD_PROBE_DROP;
1625 videoinfo->filesize += (guint64)buffer_size;
1628 _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
1631 g_mutex_unlock(&videoinfo->size_check_lock);
1633 return GST_PAD_PROBE_OK;
1637 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1639 guint64 trailer_size = 0;
1640 guint64 rec_pipe_time = 0;
1641 unsigned int remained_time = 0;
1643 GstClockTime b_time;
1645 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1646 _MMCamcorderMsgItem msg;
1647 _MMCamcorderSubContext *sc = NULL;
1648 _MMCamcorderVideoInfo *videoinfo = NULL;
1650 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1652 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1653 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1655 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1656 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1657 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1659 videoinfo = sc->info_video;
1661 b_time = GST_BUFFER_PTS(buffer);
1663 rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1665 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1666 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1671 /* check max time */
1672 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1673 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1674 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1676 if (!sc->isMaxtimePausing) {
1677 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1679 sc->isMaxtimePausing = TRUE;
1681 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1682 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1683 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1684 msg.param.recording_status.remained_time = 0;
1685 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1687 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1688 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1691 return GST_PAD_PROBE_DROP;
1694 /* calculate remained time can be recorded */
1695 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1696 remained_time = videoinfo->max_time - rec_pipe_time;
1697 } else if (videoinfo->max_size > 0) {
1698 long double max_size = (long double)videoinfo->max_size;
1699 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1701 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1704 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1705 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1706 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1707 msg.param.recording_status.remained_time = remained_time;
1708 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1711 _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1712 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1715 if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1716 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1719 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1720 record_motion_rate, videoinfo->record_drop_count);
1723 /* drop some frame if fast motion */
1724 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1725 if (record_motion_rate != (videoinfo->record_drop_count++)) {
1727 _mmcam_dbg_warn("drop frame");
1729 return GST_PAD_PROBE_DROP;
1732 videoinfo->record_drop_count = 1;
1734 _mmcam_dbg_warn("pass frame");
1738 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1739 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1742 return GST_PAD_PROBE_OK;
1746 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1748 _MMCamcorderMsgItem msg;
1749 guint64 trailer_size = 0;
1750 guint64 rec_pipe_time = 0;
1751 _MMCamcorderSubContext *sc = NULL;
1752 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1753 _MMCamcorderVideoInfo *videoinfo = NULL;
1754 unsigned int remained_time = 0;
1755 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1757 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1758 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1759 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1761 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1762 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1763 mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1765 videoinfo = sc->info_video;
1767 if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1768 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1769 return GST_PAD_PROBE_OK;
1772 rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1774 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1775 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1780 /* calculate remained time can be recorded */
1781 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1782 remained_time = videoinfo->max_time - rec_pipe_time;
1783 } else if (videoinfo->max_size > 0) {
1784 long double max_size = (long double)videoinfo->max_size;
1785 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1787 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1790 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1791 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1792 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1794 if (!sc->isMaxtimePausing) {
1795 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1797 sc->isMaxtimePausing = TRUE;
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 = 0;
1803 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1805 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1806 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1809 return GST_PAD_PROBE_DROP;
1812 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1813 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1814 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1815 msg.param.recording_status.remained_time = remained_time;
1816 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1819 _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1820 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1823 return GST_PAD_PROBE_OK;
1827 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1829 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1830 double volume = 0.0;
1833 int err = MM_ERROR_UNKNOWN;
1834 char *err_name = NULL;
1835 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1838 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1839 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1841 /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1842 err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1843 MMCAM_AUDIO_VOLUME, &volume,
1844 MMCAM_AUDIO_FORMAT, &format,
1845 MMCAM_AUDIO_CHANNEL, &channel,
1847 if (err != MM_ERROR_NONE) {
1848 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1849 SAFE_FREE(err_name);
1853 memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1855 gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1857 /* Set audio stream NULL */
1859 memset(mapinfo.data, 0, mapinfo.size);
1861 /* CALL audio stream callback */
1862 if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1863 MMCamcorderAudioStreamDataType stream;
1865 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1866 _mmcam_dbg_warn("Not ready for stream callback");
1867 gst_buffer_unmap(buffer, &mapinfo);
1868 return GST_PAD_PROBE_OK;
1871 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1872 GST_BUFFER_DATA(buffer), width, height, format);*/
1874 stream.data = (void *)mapinfo.data;
1875 stream.format = format;
1876 stream.channel = channel;
1877 stream.length = mapinfo.size;
1878 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1880 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1882 if (hcamcorder->astream_cb)
1883 hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1885 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1888 gst_buffer_unmap(buffer, &mapinfo);
1889 return GST_PAD_PROBE_OK;
1893 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1895 gboolean bret = FALSE;
1897 switch (fileformat) {
1898 case MM_FILE_FORMAT_3GP:
1899 case MM_FILE_FORMAT_MP4:
1900 bret = __mmcamcorder_add_metadata_mp4(handle);
1903 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1911 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1915 guint64 udta_size = 0;
1916 gint64 current_pos = 0;
1917 gint64 moov_pos = 0;
1918 gint64 udta_pos = 0;
1919 gdouble longitude = 0;
1920 gdouble latitude = 0;
1921 gdouble altitude = 0;
1923 int orientation = 0;
1925 char *err_name = NULL;
1926 char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1927 _MMCamcorderLocationInfo location_info = {0, 0, 0};
1928 _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1930 _MMCamcorderVideoInfo *info = NULL;
1931 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1932 _MMCamcorderSubContext *sc = NULL;
1934 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1935 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1937 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1938 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1942 info = sc->info_video;
1944 f = fopen64(info->filename, "rb+");
1946 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1947 _mmcam_dbg_err("file open failed [%s]", err_msg);
1951 mm_camcorder_get_attributes(handle, &err_name,
1952 MMCAM_TAG_LATITUDE, &latitude,
1953 MMCAM_TAG_LONGITUDE, &longitude,
1954 MMCAM_TAG_ALTITUDE, &altitude,
1955 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1956 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1959 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1960 SAFE_FREE(err_name);
1963 location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1964 location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1965 location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1966 geo_info.longitude = longitude *10000;
1967 geo_info.latitude = latitude *10000;
1968 geo_info.altitude = altitude *10000;
1969 /* find udta container.
1970 if, there are udta container, write loci box after that
1971 else, make udta container and write loci box. */
1972 if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1975 _mmcam_dbg_log("find udta container");
1978 if (fseek(f, -8L, SEEK_CUR) != 0)
1981 udta_pos = ftello(f);
1985 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1987 _mmcam_dbg_log("recorded file fread %d", nread);
1989 udta_size = _mmcamcorder_get_container_size(buf);
1991 /* goto end of udta and write 'loci' box */
1992 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1996 if (!_mmcamcorder_write_loci(f, location_info)) {
1997 _mmcam_dbg_err("failed to write loci");
2001 if (!_mmcamcorder_write_geodata(f, geo_info)) {
2002 _mmcam_dbg_err("failed to write geodata");
2007 current_pos = ftello(f);
2008 if (current_pos < 0)
2011 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
2014 _mmcam_dbg_log("No udta container");
2015 if (fseek(f, 0, SEEK_END) != 0)
2018 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
2019 _mmcam_dbg_err("failed to write udta");
2024 /* find moov container.
2025 update moov container size. */
2026 if ((current_pos = ftello(f)) < 0)
2029 if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
2030 gint64 internal_pos = ftello(f);
2032 _mmcam_dbg_log("found moov container");
2033 if (fseek(f, -8L, SEEK_CUR) != 0)
2036 moov_pos = ftello(f);
2040 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
2043 /* add orientation info */
2044 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
2045 _mmcam_dbg_err("fseek failed : errno %d", errno);
2049 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
2050 _mmcam_dbg_err("failed to find [trak] tag");
2054 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
2055 _mmcam_dbg_err("failed to find [tkhd] tag");
2059 _mmcam_dbg_log("found [tkhd] tag");
2061 /* seek to start position of composition matrix */
2062 fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR);
2064 /* update composition matrix for orientation */
2065 _mmcamcorder_update_composition_matrix(f, orientation);
2067 _mmcam_dbg_err("No 'moov' container");
2079 _mmcam_dbg_err("ftell() returns negative value.");
2085 int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
2087 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2088 _MMCamcorderSubContext *sc = NULL;
2090 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2092 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2093 mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2095 /* check video source element */
2096 if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
2097 _mmcam_dbg_warn("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
2098 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
2099 _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
2100 G_CALLBACK(__mmcamcorder_video_stream_cb),
2102 return MM_ERROR_NONE;
2104 _mmcam_dbg_err("videosrc element is not created yet");
2105 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
2110 int _mmcamcorder_video_prepare_record(MMHandleType handle)
2112 int ret = MM_ERROR_NONE;
2114 char *temp_filename = NULL;
2116 _MMCamcorderVideoInfo *info = NULL;
2117 _MMCamcorderSubContext *sc = NULL;
2118 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2120 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2122 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2123 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2124 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2126 info = sc->info_video;
2128 _mmcam_dbg_warn("start");
2130 /* create encoding pipeline */
2131 ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2132 if (ret != MM_ERROR_NONE)
2133 goto _ERR_PREPARE_RECORD;
2135 SAFE_G_FREE(info->filename);
2137 mm_camcorder_get_attributes(handle, NULL,
2138 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2140 if (temp_filename) {
2141 info->filename = g_strdup(temp_filename);
2142 if (!info->filename) {
2143 _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
2144 goto _ERR_PREPARE_RECORD;
2147 _mmcam_dbg_log("Record file name [%s]", info->filename);
2148 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2150 _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
2151 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
2154 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2156 /* Adjust display FPS */
2157 sc->display_interval = 0;
2158 sc->previous_slot_time = 0;
2160 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2161 if (ret != MM_ERROR_NONE)
2162 goto _ERR_PREPARE_RECORD;
2164 _mmcam_dbg_warn("done");
2168 _ERR_PREPARE_RECORD:
2169 /* Remove recorder pipeline and recording file which size maybe zero */
2170 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2171 if (info && info->filename) {
2172 _mmcam_dbg_log("file delete(%s)", info->filename);
2173 unlink(info->filename);