[libmm-camcorder] g_free and g_printf function fixes
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_audiorec.c
index 5afa857..4cfbb72 100644 (file)
@@ -39,7 +39,7 @@
 #define _MMCAMCORDER_AUDIO_MINIMUM_SPACE        (100*1024)
 #define _MMCAMCORDER_AUDIO_MARGIN_SPACE         (1*1024)
 #define _MMCAMCORDER_RETRIAL_COUNT              10
-#define _MMCAMCORDER_FRAME_WAIT_TIME            20000 /* micro second */
+#define _MMCAMCORDER_FRAME_WAIT_TIME            200000 /* micro second */
 #define _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL  10
 
 /*---------------------------------------------------------------------------------------
@@ -49,7 +49,7 @@
 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
 static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle);
-static void __mmcamcorder_audiorec_pad_added_cb(GstElement *element, GstPad *pad, MMHandleType handle);
+static gboolean __mmcamcorder_audio_add_metadata_info_m4a(MMHandleType handle);
 
 /*=======================================================================================
 |  FUNCTION DEFINITIONS                                                                        |
@@ -197,19 +197,11 @@ static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle)
        gst_object_unref(srcpad);
        srcpad = NULL;
 
-       if (info->bMuxing) {
-               MMCAMCORDER_SIGNAL_CONNECT(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst,
-                                          _MMCAMCORDER_HANDLER_AUDIOREC,
-                                          "pad-added",
-                                          __mmcamcorder_audiorec_pad_added_cb,
-                                          hcamcorder);
-       } else {
-               srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
-               MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC,
-                                            __mmcamcorder_audio_dataprobe_record, hcamcorder);
-               gst_object_unref(srcpad);
-               srcpad = NULL;
-       }
+       srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
+       MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC,
+                                    __mmcamcorder_audio_dataprobe_record, hcamcorder);
+       gst_object_unref(srcpad);
+       srcpad = NULL;
 
        bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
 
@@ -217,7 +209,7 @@ static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle)
        hcamcorder->pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder);
 
        /* set sync callback */
-       gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, hcamcorder, NULL);
+       gst_bus_set_sync_handler(bus, _mmcamcorder_audio_pipeline_bus_sync_callback, hcamcorder, NULL);
 
        gst_object_unref(bus);
        bus = NULL;
@@ -357,9 +349,7 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
        int cmd = command;
        int ret = MM_ERROR_NONE;
        int err = 0;
-       int size=0;
        guint64 free_space = 0;
-       char *dir_name = NULL;
        char *err_attr_name = NULL;
 
        GstElement *pipeline = NULL;
@@ -389,7 +379,10 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                        guint imax_size = 0;
                        guint imax_time = 0;
                        char *temp_filename = NULL;
+                       char *dir_name = NULL;
                        int file_system_type = 0;
+                       int filename_length = 0;
+                       int root_directory_length = 0;
 
                        if(sc->pipeline_time) {
                                gst_element_set_start_time(pipeline, sc->pipeline_time);
@@ -400,7 +393,8 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                                                          MMCAM_TARGET_MAX_SIZE, &imax_size,
                                                          MMCAM_TARGET_TIME_LIMIT, &imax_time,
                                                          MMCAM_FILE_FORMAT, &(info->fileformat),
-                                                         MMCAM_TARGET_FILENAME, &temp_filename, &size,
+                                                         MMCAM_TARGET_FILENAME, &temp_filename, &filename_length,
+                                                         MMCAM_ROOT_DIRECTORY, &hcamcorder->root_directory, &root_directory_length,
                                                          NULL);
                        if (ret != MM_ERROR_NONE) {
                                _mmcam_dbg_warn("failed to get attribute. (%s:%x)", err_attr_name, ret);
@@ -414,7 +408,7 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                                goto _ERR_CAMCORDER_AUDIO_COMMAND;
                        }
 
-                       info->filename = strdup(temp_filename);
+                       info->filename = g_strdup(temp_filename);
                        if (!info->filename) {
                                _mmcam_dbg_err("STRDUP was failed");
                                goto _ERR_CAMCORDER_AUDIO_COMMAND;
@@ -422,7 +416,7 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
 
                        _mmcam_dbg_log("Record start : set file name using attribute - %s\n ",info->filename);
 
-                       MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
+                       MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
 
                        sc->ferror_send = FALSE;
                        sc->ferror_count = 0;
@@ -446,8 +440,9 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                        /* TODO : check free space before recording start */
                        dir_name = g_path_get_dirname(info->filename);
                        if (dir_name) {
-                               err = _mmcamcorder_get_freespace(dir_name, &free_space);
-                               _mmcam_dbg_warn("current space for recording - %s :[%" G_GUINT64_FORMAT "]" ,dir_name, free_space);
+                               err = _mmcamcorder_get_freespace(dir_name, hcamcorder->root_directory, &free_space);
+
+                               _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "]", dir_name, free_space);
 
                                if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) {
                                        /* MSDOS_SUPER_MAGIC : 0x4d44 */
@@ -546,8 +541,7 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                if (info->filename) {
                        _mmcam_dbg_log("file delete(%s)", info->filename);
                        unlink(info->filename);
-                       g_free(info->filename);
-                       info->filename = NULL;
+                       SAFE_G_FREE(info->filename);
                }
                break;
 
@@ -580,7 +574,15 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                }
 
                if (audioSrc) {
-                       ret = gst_element_send_event(audioSrc, gst_event_new_eos());
+                       if (gst_element_send_event(audioSrc, gst_event_new_eos()) == FALSE) {
+                               _mmcam_dbg_err("send EOS failed");
+                               info->b_commiting = FALSE;
+                               ret = MM_ERROR_CAMCORDER_INTERNAL;
+                               goto _ERR_CAMCORDER_AUDIO_COMMAND;
+                       }
+
+                       _mmcam_dbg_log("send EOS done");
+
                        /* for pause -> commit case */
                        if (_mmcamcorder_get_state((MMHandleType)hcamcorder) == MM_CAMCORDER_STATE_PAUSED) {
                                ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
@@ -589,6 +591,11 @@ _mmcamcorder_audio_command(MMHandleType handle, int command)
                                        goto _ERR_CAMCORDER_AUDIO_COMMAND;
                                }
                        }
+               } else {
+                       _mmcam_dbg_err("No audio stream source");
+                       info->b_commiting = FALSE;
+                       ret = MM_ERROR_CAMCORDER_INTERNAL;
+                       goto _ERR_CAMCORDER_AUDIO_COMMAND;
                }
 
                /* wait until finishing EOS */
@@ -647,16 +654,23 @@ int _mmcamcorder_audio_handle_eos(MMHandleType handle)
 
        /* Send recording report message to application */
        msg.id = MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED;
-       report = (MMCamRecordingReport*) malloc(sizeof(MMCamRecordingReport));
+       report = (MMCamRecordingReport*) g_malloc(sizeof(MMCamRecordingReport));
        if (!report) {
                _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
                return FALSE;
        }
 
-       report->recording_filename = strdup(info->filename);
+/* START TAG HERE */
+       // MM_AUDIO_CODEC_AAC + MM_FILE_FORMAT_MP4
+       if(info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4){
+               __mmcamcorder_audio_add_metadata_info_m4a(handle);
+       }
+/* END TAG HERE */
+
+       report->recording_filename = g_strdup(info->filename);
        msg.param.data= report;
 
-       _mmcamcroder_send_message(handle, &msg);
+       _mmcamcorder_send_message(handle, &msg);
 
        if (info->bMuxing) {
                MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
@@ -671,8 +685,7 @@ int _mmcamcorder_audio_handle_eos(MMHandleType handle)
        sc->isMaxsizePausing = FALSE;
        sc->isMaxtimePausing = FALSE;
 
-       g_free(info->filename);
-       info->filename = NULL;
+       SAFE_G_FREE(info->filename);
 
        _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
 
@@ -722,7 +735,7 @@ __mmcamcorder_get_decibel(unsigned char* raw, int size, MMCamcorderAudioFormat f
        }
 
        if (count > 0) {
-               rms = sqrt( square_sum/count );
+               rms = sqrt( (double)square_sum/(double)count );
                if (depthByte == 1) {
                        db = 20 * log10( rms/MAX_AMPLITUDE_MEAN_08BIT );
                } else {
@@ -750,10 +763,12 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad
        int err = MM_ERROR_UNKNOWN;
        char *err_name = NULL;
        GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
-       GstMapInfo mapinfo = GST_MAP_INFO_INIT;
+       GstMapInfo mapinfo;
 
        mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
 
+       memset(&mapinfo, 0x0, sizeof(GstMapInfo));
+
        /* Set volume to audio input */
        err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
                                                                        MMCAM_AUDIO_VOLUME, &volume,
@@ -777,7 +792,7 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad
 
        msg.id = MM_MESSAGE_CAMCORDER_CURRENT_VOLUME;
        msg.param.rec_volume_dB = curdcb;
-       _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+       _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
 
        /* CALL audio stream callback */
        if ((hcamcorder->astream_cb) && buffer && mapinfo.data && mapinfo.size > 0)
@@ -818,27 +833,6 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad
 }
 
 
-static void
-__mmcamcorder_audiorec_pad_added_cb(GstElement *element, GstPad *pad,  MMHandleType handle)
-{
-       mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
-
-       _mmcam_dbg_log("ENTER(%s)", GST_PAD_NAME(pad));
-       //FIXME : the name of audio sink pad of wavparse, oggmux doesn't have 'audio'. How could I handle the name?
-       if((strstr(GST_PAD_NAME(pad), "audio")) || (strstr(GST_PAD_NAME(pad), "sink")))
-       {
-               MMCAMCORDER_ADD_BUFFER_PROBE(pad, _MMCAMCORDER_HANDLER_AUDIOREC,
-                       __mmcamcorder_audio_dataprobe_record, hcamcorder);
-       }
-       else
-       {
-               _mmcam_dbg_warn("Unknow pad is added, check it : [%s]", GST_PAD_NAME(pad));
-       }
-
-       return;
-}
-
-
 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
 {
        static int count = 0;
@@ -901,7 +895,17 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPa
        /* to minimizing free space check overhead */
        count = count % _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL;
        if (count++ == 0) {
-               gint free_space_ret = _mmcamcorder_get_freespace(filename, &free_space);
+               char *dir_name = g_path_get_dirname(filename);
+               gint free_space_ret = 0;
+
+               if (dir_name) {
+                       free_space_ret = _mmcamcorder_get_freespace(dir_name, hcamcorder->root_directory, &free_space);
+                       g_free(dir_name);
+                       dir_name = NULL;
+               } else {
+                       _mmcam_dbg_err("failed to get dir name from [%s]", filename);
+                       free_space_ret = -1;
+               }
 
                /*_mmcam_dbg_log("check free space for recording");*/
 
@@ -917,7 +921,7 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPa
                                } else {
                                        msg.param.code = MM_ERROR_FILE_READ;
                                }
-                               _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+                               _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
                        } else {
                                sc->ferror_count++;
                        }
@@ -939,7 +943,7 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPa
 
                                sc->isMaxsizePausing = TRUE;
                                msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
-                               _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+                               _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
 
                                return GST_PAD_PROBE_DROP; /* skip this buffer */
                        }
@@ -984,13 +988,13 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPa
                msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
                msg.param.recording_status.filesize = (unsigned long long)((audioinfo->filesize + trailer_size) >> 10);
                msg.param.recording_status.remained_time = 0;
-               _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+               _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
 
                _mmcam_dbg_warn("Last filesize sent by message : %d", audioinfo->filesize + trailer_size);
 
                sc->isMaxsizePausing = TRUE;
                msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
-               _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+               _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
 
                /* skip this buffer */
                return GST_PAD_PROBE_DROP;
@@ -1009,7 +1013,7 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPa
 
                sc->isMaxtimePausing = TRUE;
                msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
-               _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+               _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
 
                /* skip this buffer */
                return GST_PAD_PROBE_DROP;
@@ -1023,7 +1027,7 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPa
                msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
                msg.param.recording_status.filesize = (unsigned long long)((audioinfo->filesize + trailer_size) >> 10);
                msg.param.recording_status.remained_time = remained_time;
-               _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+               _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
 
                return GST_PAD_PROBE_OK;
        } else {
@@ -1031,3 +1035,160 @@ static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPa
                return GST_PAD_PROBE_DROP;
        }
 }
+
+/* START TAG HERE */
+static gboolean __mmcamcorder_audio_add_metadata_info_m4a(MMHandleType handle)
+{
+       FILE *f = NULL;
+       guchar buf[4];
+       guint64 udta_size = 0;
+       gint64 current_pos = 0;
+       gint64 moov_pos = 0;
+       gint64 udta_pos = 0;
+       // supporting audio geo tag for mobile
+       int gps_enable = 0;
+       gdouble longitude = 0;
+       gdouble latitude = 0;
+       gdouble altitude = 0;
+       _MMCamcorderLocationInfo geo_info = {0,0,0};
+       _MMCamcorderLocationInfo loc_info = {0,0,0};
+
+       char err_msg[128] = {'\0',};
+
+       _MMCamcorderAudioInfo *info = NULL;
+       mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+       _MMCamcorderSubContext *sc = NULL;
+
+       mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+       sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+       mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+       mmf_return_val_if_fail(sc->info_audio, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+       info = sc->info_audio;
+       mm_camcorder_get_attributes(handle, NULL,
+                                   MMCAM_TAG_GPS_ENABLE, &gps_enable,
+                                   NULL);
+
+       if (gps_enable) {
+               mm_camcorder_get_attributes(handle, NULL,
+                                           MMCAM_TAG_LATITUDE, &latitude,
+                                           MMCAM_TAG_LONGITUDE, &longitude,
+                                           MMCAM_TAG_ALTITUDE, &altitude,
+                                           NULL);
+               loc_info.longitude = _mmcamcorder_double_to_fix(longitude);
+               loc_info.latitude = _mmcamcorder_double_to_fix(latitude);
+               loc_info.altitude = _mmcamcorder_double_to_fix(altitude);
+               geo_info.longitude = longitude *10000;
+               geo_info.latitude = latitude *10000;
+               geo_info.altitude = altitude *10000;
+       }
+
+       f = fopen64(info->filename, "rb+");
+       if (f == NULL) {
+               strerror_r(errno, err_msg, 128);
+               _mmcam_dbg_err("file open failed [%s]", err_msg);
+               return FALSE;
+       }
+
+       /* find udta container.
+          if, there are udta container, write loci box after that
+          else, make udta container and write loci box. */
+       if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u','d','t','a'), TRUE)) {
+               size_t nread = 0;
+
+               _mmcam_dbg_log("find udta container");
+
+               /* read size */
+               if (fseek(f, -8L, SEEK_CUR) != 0) {
+                       goto fail;
+               }
+
+               udta_pos = ftello(f);
+               if (udta_pos < 0) {
+                       goto ftell_fail;
+               }
+
+               nread = fread(&buf, sizeof(char), sizeof(buf), f);
+
+               _mmcam_dbg_log("recorded file fread %d", nread);
+
+               udta_size = _mmcamcorder_get_container_size(buf);
+
+               /* goto end of udta and write 'smta' box */
+               if (fseek(f, (udta_size-4L), SEEK_CUR) != 0) {
+                       goto fail;
+               }
+
+               if (gps_enable) {
+                       if (!_mmcamcorder_write_loci(f, loc_info)) {
+                               goto fail;
+                       }
+
+                       if (!_mmcamcorder_write_geodata( f, geo_info )) {
+                               goto fail;
+                       }
+               }
+
+               current_pos = ftello(f);
+               if (current_pos < 0) {
+                       goto ftell_fail;
+               }
+
+               if (!_mmcamcorder_update_size(f, udta_pos, current_pos)) {
+                       goto fail;
+               }
+       } else {
+               _mmcam_dbg_log("No udta container");
+               if (fseek(f, 0, SEEK_END) != 0) {
+                       goto fail;
+               }
+
+               if (!_mmcamcorder_write_udta(f, gps_enable, loc_info, geo_info)) {
+                       goto fail;
+               }
+       }
+
+       /* find moov container.
+          update moov container size. */
+       if((current_pos = ftello(f))<0)
+               goto ftell_fail;
+
+       if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('m','o','o','v'), TRUE)) {
+
+               _mmcam_dbg_log("found moov container");
+               if (fseek(f, -8L, SEEK_CUR) !=0) {
+                       goto fail;
+               }
+
+               moov_pos = ftello(f);
+               if (moov_pos < 0) {
+                       goto ftell_fail;
+               }
+
+               if (!_mmcamcorder_update_size(f, moov_pos, current_pos)) {
+                       goto fail;
+               }
+
+
+       } else {
+               _mmcam_dbg_err("No 'moov' container");
+               goto fail;
+       }
+
+       fclose(f);
+
+       return TRUE;
+
+fail:
+       fclose(f);
+       return FALSE;
+
+ftell_fail:
+       _mmcam_dbg_err("ftell() returns negative value.");
+       fclose(f);
+       return FALSE;
+}
+
+/* END TAG HERE */
+