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:
1074 if (info->b_commiting) {
1075 _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command);
1076 return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
1078 _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
1079 info->b_commiting = TRUE;
1080 sc->bget_eos = FALSE;
1083 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
1084 if (sc->audio_disable) {
1085 /* check only video frame */
1086 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1087 hcamcorder->capture_in_recording == FALSE) {
1089 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1090 _mmcam_dbg_err("Commit fail, frame count is %llu, capturing %d",
1091 info->video_frame_count, hcamcorder->capture_in_recording);
1093 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
1094 _mmcam_dbg_warn("video frames are enough. keep going...");
1096 info->b_commiting = FALSE;
1097 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1100 _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %llu, capturing %d",
1101 count, info->video_frame_count, hcamcorder->capture_in_recording);
1104 /* check both of video and audio frame */
1105 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1106 info->audio_frame_count &&
1107 hcamcorder->capture_in_recording == FALSE) {
1109 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1110 _mmcam_dbg_err("Commit fail, VIDEO[%llu], AUDIO [%llu], capturing %d",
1111 info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1113 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
1114 _mmcam_dbg_warn("video/audio frames are enough. keep going...");
1116 info->b_commiting = FALSE;
1117 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1120 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1122 _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu], capturing %d",
1123 count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1127 if (hcamcorder->capture_in_recording) {
1128 gint64 end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND);
1129 if (_MMCAMCORDER_CMD_WAIT_UNTIL(handle, end_time)) {
1130 _mmcam_dbg_warn("signal received");
1132 _mmcam_dbg_warn("timeout");
1135 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
1139 /* block push buffer */
1140 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1141 _mmcam_dbg_log("block push buffer to appsrc");
1143 if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
1144 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
1145 _mmcam_dbg_warn("VIDEO: send eos to appsrc done");
1147 _mmcam_dbg_err("VIDEO: send EOS failed");
1148 info->b_commiting = FALSE;
1149 ret = MM_ERROR_CAMCORDER_INTERNAL;
1150 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1153 _mmcam_dbg_err("No video stream source");
1154 info->b_commiting = FALSE;
1155 ret = MM_ERROR_CAMCORDER_INTERNAL;
1156 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1159 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
1160 if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
1161 _mmcam_dbg_warn("AUDIO: send eos to audiosrc done");
1163 _mmcam_dbg_err("AUDIO: send EOS failed");
1164 info->b_commiting = FALSE;
1165 ret = MM_ERROR_CAMCORDER_INTERNAL;
1166 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1169 _mmcam_dbg_log("No audio stream");
1173 sc->display_interval = 0;
1174 sc->previous_slot_time = 0;
1177 _mmcam_dbg_log("Start to wait EOS");
1178 ret = _mmcamcorder_get_eos_message(handle);
1179 if (ret != MM_ERROR_NONE) {
1180 info->b_commiting = FALSE;
1181 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1185 hcamcorder->capture_in_recording = FALSE;
1189 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1190 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1193 return MM_ERROR_NONE;
1195 _ERR_CAMCORDER_VIDEO_COMMAND:
1196 if (command == _MMCamcorder_CMD_RECORD)
1197 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1203 int _mmcamcorder_video_handle_eos(MMHandleType handle)
1205 int ret = MM_ERROR_NONE;
1207 guint64 file_size = 0;
1209 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1210 _MMCamcorderSubContext *sc = NULL;
1211 _MMCamcorderVideoInfo *info = NULL;
1212 _MMCamcorderMsgItem msg;
1213 MMCamRecordingReport *report = NULL;
1215 mmf_return_val_if_fail(hcamcorder, FALSE);
1217 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1218 mmf_return_val_if_fail(sc, FALSE);
1219 mmf_return_val_if_fail(sc->info_video, FALSE);
1221 info = sc->info_video;
1225 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1226 /* Play record stop sound */
1227 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1229 _mmcam_dbg_warn("Play stop sound through pulseaudio");
1231 _mmcamcorder_sound_init(handle);
1233 _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, TRUE);
1235 _mmcamcorder_sound_finalize(handle);
1238 /* remove blocking part */
1239 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1241 mm_camcorder_get_attributes(handle, NULL,
1242 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1245 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1246 if (ret != MM_ERROR_NONE)
1247 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1249 /* set recording hint */
1250 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1252 /* stop video stream */
1253 if (info->record_dual_stream) {
1254 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1256 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1258 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1259 gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1261 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1263 _mmcam_dbg_err("failed to get camera control");
1267 if (enabletag && !(sc->ferror_send)) {
1268 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1270 _mmcam_dbg_log("Writing location information SUCCEEDED !!");
1272 _mmcam_dbg_err("Writing location information FAILED !!");
1276 /* Check file size */
1277 if (info->max_size > 0) {
1278 _mmcamcorder_get_file_size(info->filename, &file_size);
1279 _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
1280 info->max_size, file_size);
1282 if (file_size > info->max_size) {
1283 _MMCamcorderMsgItem message;
1284 _mmcam_dbg_err("File size is greater than max size !!");
1285 message.id = MM_MESSAGE_CAMCORDER_ERROR;
1286 message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1287 _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1291 if (info->restart_preview) {
1293 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1294 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1295 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1297 _mmcam_dbg_log("Set state of pipeline as READY");
1298 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1300 /* check decoder recreation */
1301 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1302 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1303 ret = MM_ERROR_CAMCORDER_INTERNAL;
1307 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1308 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1309 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1311 if (ret != MM_ERROR_NONE) {
1312 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1313 msg.param.code = ret;
1314 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1315 _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1318 /* reset restart_preview for inset window layout */
1319 info->restart_preview = FALSE;
1321 /* recover preview size */
1322 _mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height);
1324 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1325 /* Do not return when error is occurred.
1326 Recording file was created successfully, but starting pipeline failed */
1327 if (ret != MM_ERROR_NONE) {
1328 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1329 msg.param.code = ret;
1330 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1331 _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1334 _mmcam_dbg_log("No need to restart preview");
1337 /* Send recording report to application */
1338 msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1339 report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1341 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1343 report->recording_filename = g_strdup(info->filename);
1344 msg.param.data = report;
1346 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1350 sc->pipeline_time = 0;
1352 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1353 sc->isMaxtimePausing = FALSE;
1354 hcamcorder->error_occurs = FALSE;
1356 info->video_frame_count = 0;
1357 info->audio_frame_count = 0;
1359 info->b_commiting = FALSE;
1361 if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1362 /* check recording stop sound */
1363 _mmcamcorder_sound_solo_play_wait(handle);
1366 _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1372 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1374 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1375 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1377 _MMCamcorderSubContext *sc = NULL;
1378 _MMCamcorderVideoInfo *videoinfo = NULL;
1379 _MMCamcorderMsgItem msg;
1380 guint64 buffer_size = 0;
1381 guint64 trailer_size = 0;
1382 guint64 max_size = 0;
1384 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1385 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1386 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1388 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1389 videoinfo = sc->info_video;
1391 /* get buffer size */
1392 if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1393 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1394 return GST_PAD_PROBE_OK;
1397 buffer_size = mapinfo.size;
1398 gst_buffer_unmap(buffer, &mapinfo);
1400 /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1402 g_mutex_lock(&videoinfo->size_check_lock);
1404 if (videoinfo->audio_frame_count == 0) {
1405 videoinfo->filesize += buffer_size;
1406 videoinfo->audio_frame_count++;
1407 g_mutex_unlock(&videoinfo->size_check_lock);
1408 return GST_PAD_PROBE_OK;
1411 if (sc->ferror_send || sc->isMaxsizePausing) {
1412 _mmcam_dbg_warn("Recording is paused, drop frames");
1413 g_mutex_unlock(&videoinfo->size_check_lock);
1414 return GST_PAD_PROBE_DROP;
1417 /* get trailer size */
1418 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1419 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1424 /* check max size of recorded file */
1425 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1426 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1427 GstState pipeline_state = GST_STATE_VOID_PENDING;
1428 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1429 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1430 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1431 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1432 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1434 if (!sc->isMaxsizePausing) {
1435 sc->isMaxsizePausing = TRUE;
1436 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1437 if (pipeline_state == GST_STATE_PLAYING)
1438 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1440 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1441 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1444 g_mutex_unlock(&videoinfo->size_check_lock);
1449 videoinfo->filesize += buffer_size;
1450 videoinfo->audio_frame_count++;
1452 g_mutex_unlock(&videoinfo->size_check_lock);
1454 return GST_PAD_PROBE_OK;
1458 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1463 guint64 free_space = 0;
1464 guint64 buffer_size = 0;
1465 guint64 trailer_size = 0;
1466 guint64 queued_buffer = 0;
1467 guint64 max_size = 0;
1468 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1470 storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1472 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1473 _MMCamcorderMsgItem msg;
1474 _MMCamcorderSubContext *sc = NULL;
1475 _MMCamcorderVideoInfo *videoinfo = NULL;
1477 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1478 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1480 sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1481 mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1482 videoinfo = sc->info_video;
1484 /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1485 if (sc->ferror_send) {
1486 _mmcam_dbg_warn("file write error, drop frames");
1487 return GST_PAD_PROBE_DROP;
1490 gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1491 buffer_size = mapinfo.size;
1492 gst_buffer_unmap(buffer, &mapinfo);
1494 videoinfo->video_frame_count++;
1495 if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1496 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1497 info->video_frame_count); */
1498 g_mutex_lock(&videoinfo->size_check_lock);
1499 videoinfo->filesize += buffer_size;
1500 g_mutex_unlock(&videoinfo->size_check_lock);
1501 return GST_PAD_PROBE_OK;
1504 /* get trailer size */
1505 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1506 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);
1566 if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
1567 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1570 queued_buffer = aq_size + vq_size;
1572 if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1573 _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
1574 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
1575 " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
1576 free_space, trailer_size, buffer_size, queued_buffer);
1578 if (!sc->isMaxsizePausing) {
1579 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1580 sc->isMaxsizePausing = TRUE;
1582 msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
1583 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1586 return GST_PAD_PROBE_DROP;
1589 g_mutex_lock(&videoinfo->size_check_lock);
1591 /* check max size of recorded file */
1592 max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1593 if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1594 GstState pipeline_state = GST_STATE_VOID_PENDING;
1595 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1596 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1597 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1598 " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1599 videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1601 if (!sc->isMaxsizePausing) {
1602 sc->isMaxsizePausing = TRUE;
1603 gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1604 if (pipeline_state == GST_STATE_PLAYING)
1605 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1607 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1608 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1611 g_mutex_unlock(&videoinfo->size_check_lock);
1613 return GST_PAD_PROBE_DROP;
1616 videoinfo->filesize += (guint64)buffer_size;
1619 _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
1622 g_mutex_unlock(&videoinfo->size_check_lock);
1624 return GST_PAD_PROBE_OK;
1628 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1630 guint64 trailer_size = 0;
1631 guint64 rec_pipe_time = 0;
1632 unsigned int remained_time = 0;
1634 GstClockTime b_time;
1636 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1637 _MMCamcorderMsgItem msg;
1638 _MMCamcorderSubContext *sc = NULL;
1639 _MMCamcorderVideoInfo *videoinfo = NULL;
1641 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1643 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1644 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1646 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1647 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1648 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1650 videoinfo = sc->info_video;
1652 b_time = GST_BUFFER_PTS(buffer);
1654 rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1656 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1657 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1662 /* check max time */
1663 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1664 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1665 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1667 if (!sc->isMaxtimePausing) {
1668 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1670 sc->isMaxtimePausing = TRUE;
1672 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1673 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1674 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1675 msg.param.recording_status.remained_time = 0;
1676 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1678 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1679 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1682 return GST_PAD_PROBE_DROP;
1685 /* calculate remained time can be recorded */
1686 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1687 remained_time = videoinfo->max_time - rec_pipe_time;
1688 } else if (videoinfo->max_size > 0) {
1689 long double max_size = (long double)videoinfo->max_size;
1690 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1692 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1695 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1696 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1697 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1698 msg.param.recording_status.remained_time = remained_time;
1699 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1702 _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1703 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1706 if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1707 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1710 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1711 record_motion_rate, videoinfo->record_drop_count);
1714 /* drop some frame if fast motion */
1715 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1716 if (record_motion_rate != (videoinfo->record_drop_count++)) {
1718 _mmcam_dbg_warn("drop frame");
1720 return GST_PAD_PROBE_DROP;
1723 videoinfo->record_drop_count = 1;
1725 _mmcam_dbg_warn("pass frame");
1729 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1730 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1733 return GST_PAD_PROBE_OK;
1737 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1739 _MMCamcorderMsgItem msg;
1740 guint64 trailer_size = 0;
1741 guint64 rec_pipe_time = 0;
1742 _MMCamcorderSubContext *sc = NULL;
1743 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1744 _MMCamcorderVideoInfo *videoinfo = NULL;
1745 unsigned int remained_time = 0;
1746 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1748 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1749 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1750 sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1752 mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1753 mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1754 mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1756 videoinfo = sc->info_video;
1758 if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1759 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1760 return GST_PAD_PROBE_OK;
1763 rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1765 if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) {
1766 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1771 /* calculate remained time can be recorded */
1772 if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1773 remained_time = videoinfo->max_time - rec_pipe_time;
1774 } else if (videoinfo->max_size > 0) {
1775 long double max_size = (long double)videoinfo->max_size;
1776 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1778 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1781 if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1782 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1783 rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1785 if (!sc->isMaxtimePausing) {
1786 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1788 sc->isMaxtimePausing = TRUE;
1790 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1791 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1792 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1793 msg.param.recording_status.remained_time = 0;
1794 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1796 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1797 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1800 return GST_PAD_PROBE_DROP;
1803 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1804 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1805 msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1806 msg.param.recording_status.remained_time = remained_time;
1807 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1810 _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1811 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1814 return GST_PAD_PROBE_OK;
1818 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1820 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1821 double volume = 0.0;
1824 int err = MM_ERROR_UNKNOWN;
1825 char *err_name = NULL;
1826 GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1829 mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1830 mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1832 /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1833 err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1834 MMCAM_AUDIO_VOLUME, &volume,
1835 MMCAM_AUDIO_FORMAT, &format,
1836 MMCAM_AUDIO_CHANNEL, &channel,
1838 if (err != MM_ERROR_NONE) {
1839 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1840 SAFE_FREE(err_name);
1844 memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1846 gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1848 /* Set audio stream NULL */
1850 memset(mapinfo.data, 0, mapinfo.size);
1852 /* CALL audio stream callback */
1853 if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1854 MMCamcorderAudioStreamDataType stream;
1856 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1857 _mmcam_dbg_warn("Not ready for stream callback");
1858 gst_buffer_unmap(buffer, &mapinfo);
1859 return GST_PAD_PROBE_OK;
1862 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1863 GST_BUFFER_DATA(buffer), width, height, format);*/
1865 stream.data = (void *)mapinfo.data;
1866 stream.format = format;
1867 stream.channel = channel;
1868 stream.length = mapinfo.size;
1869 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1871 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1873 if (hcamcorder->astream_cb)
1874 hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1876 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1879 gst_buffer_unmap(buffer, &mapinfo);
1880 return GST_PAD_PROBE_OK;
1884 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1886 gboolean bret = FALSE;
1888 switch (fileformat) {
1889 case MM_FILE_FORMAT_3GP:
1890 case MM_FILE_FORMAT_MP4:
1891 bret = __mmcamcorder_add_metadata_mp4(handle);
1894 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1902 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1906 guint64 udta_size = 0;
1907 gint64 current_pos = 0;
1908 gint64 moov_pos = 0;
1909 gint64 udta_pos = 0;
1910 gdouble longitude = 0;
1911 gdouble latitude = 0;
1912 gdouble altitude = 0;
1914 int orientation = 0;
1916 char *err_name = NULL;
1917 char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1918 _MMCamcorderLocationInfo location_info = {0, 0, 0};
1919 _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1921 _MMCamcorderVideoInfo *info = NULL;
1922 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1923 _MMCamcorderSubContext *sc = NULL;
1925 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1926 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1928 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1929 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1933 info = sc->info_video;
1935 f = fopen64(info->filename, "rb+");
1937 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1938 _mmcam_dbg_err("file open failed [%s]", err_msg);
1942 mm_camcorder_get_attributes(handle, &err_name,
1943 MMCAM_TAG_LATITUDE, &latitude,
1944 MMCAM_TAG_LONGITUDE, &longitude,
1945 MMCAM_TAG_ALTITUDE, &altitude,
1946 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1947 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1950 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1951 SAFE_FREE(err_name);
1954 location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1955 location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1956 location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1957 geo_info.longitude = longitude *10000;
1958 geo_info.latitude = latitude *10000;
1959 geo_info.altitude = altitude *10000;
1960 /* find udta container.
1961 if, there are udta container, write loci box after that
1962 else, make udta container and write loci box. */
1963 if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1966 _mmcam_dbg_log("find udta container");
1969 if (fseek(f, -8L, SEEK_CUR) != 0)
1972 udta_pos = ftello(f);
1976 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1978 _mmcam_dbg_log("recorded file fread %d", nread);
1980 udta_size = _mmcamcorder_get_container_size(buf);
1982 /* goto end of udta and write 'loci' box */
1983 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1987 if (!_mmcamcorder_write_loci(f, location_info)) {
1988 _mmcam_dbg_err("failed to write loci");
1992 if (!_mmcamcorder_write_geodata(f, geo_info)) {
1993 _mmcam_dbg_err("failed to write geodata");
1998 current_pos = ftello(f);
1999 if (current_pos < 0)
2002 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
2005 _mmcam_dbg_log("No udta container");
2006 if (fseek(f, 0, SEEK_END) != 0)
2009 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
2010 _mmcam_dbg_err("failed to write udta");
2015 /* find moov container.
2016 update moov container size. */
2017 if ((current_pos = ftello(f)) < 0)
2020 if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
2021 gint64 internal_pos = ftello(f);
2023 _mmcam_dbg_log("found moov container");
2024 if (fseek(f, -8L, SEEK_CUR) != 0)
2027 moov_pos = ftello(f);
2031 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
2034 /* add orientation info */
2035 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
2036 _mmcam_dbg_err("fseek failed : errno %d", errno);
2040 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
2041 _mmcam_dbg_err("failed to find [trak] tag");
2045 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
2046 _mmcam_dbg_err("failed to find [tkhd] tag");
2050 _mmcam_dbg_log("found [tkhd] tag");
2052 /* seek to start position of composition matrix */
2053 fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR);
2055 /* update composition matrix for orientation */
2056 _mmcamcorder_update_composition_matrix(f, orientation);
2058 _mmcam_dbg_err("No 'moov' container");
2070 _mmcam_dbg_err("ftell() returns negative value.");
2076 int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
2078 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2079 _MMCamcorderSubContext *sc = NULL;
2081 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2083 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2084 mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2086 /* check video source element */
2087 if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
2088 _mmcam_dbg_warn("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
2089 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
2090 _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
2091 G_CALLBACK(__mmcamcorder_video_stream_cb),
2093 return MM_ERROR_NONE;
2095 _mmcam_dbg_err("videosrc element is not created yet");
2096 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
2101 int _mmcamcorder_video_prepare_record(MMHandleType handle)
2103 int ret = MM_ERROR_NONE;
2105 char *temp_filename = NULL;
2107 _MMCamcorderVideoInfo *info = NULL;
2108 _MMCamcorderSubContext *sc = NULL;
2109 mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2111 mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2113 sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2114 mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2115 mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2117 info = sc->info_video;
2119 _mmcam_dbg_warn("start");
2121 /* create encoding pipeline */
2122 ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2123 if (ret != MM_ERROR_NONE)
2124 goto _ERR_PREPARE_RECORD;
2126 SAFE_G_FREE(info->filename);
2128 mm_camcorder_get_attributes(handle, NULL,
2129 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2131 if (temp_filename) {
2132 info->filename = g_strdup(temp_filename);
2133 if (!info->filename) {
2134 _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
2135 goto _ERR_PREPARE_RECORD;
2138 _mmcam_dbg_log("Record file name [%s]", info->filename);
2139 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2141 _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
2142 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
2145 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2147 /* Adjust display FPS */
2148 sc->display_interval = 0;
2149 sc->previous_slot_time = 0;
2151 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2152 if (ret != MM_ERROR_NONE)
2153 goto _ERR_PREPARE_RECORD;
2155 _mmcam_dbg_warn("done");
2159 _ERR_PREPARE_RECORD:
2160 /* Remove recorder pipeline and recording file which size maybe zero */
2161 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2162 if (info && info->filename) {
2163 _mmcam_dbg_log("file delete(%s)", info->filename);
2164 unlink(info->filename);