fix double free
[platform/core/multimedia/libmm-streamrecorder.git] / src / include / mm_streamrecorder_gstcommon.h
1 /*
2  * libmm-streamrecorder
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyuntae Kim <ht1211.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #ifndef __MM_STREAMRECORDER_GSTCOMMON_H__
23 #define __MM_STREAMRECORDER_GSTCOMMON_H__
24
25 /*=======================================================================================
26 | INCLUDE FILES                                                                         |
27 ========================================================================================*/
28 #include <mm_types.h>
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 /*=======================================================================================
35 | GLOBAL DEFINITIONS AND DECLARATIONS FOR STREAMRECORDER                                        |
36 ========================================================================================*/
37
38 /*=======================================================================================
39 | MACRO DEFINITIONS                                                                     |
40 ========================================================================================*/
41
42 /* gstreamer element creation macro */
43 #define _MMSTREAMRECORDER_PIPELINE_MAKE(sub_context, element, eid, name /*char* */, err) \
44         if (element[eid].gst != NULL) { \
45                 _mmstreamrec_dbg_err("The element(Pipeline) is existed. element_id=[%d], name=[%s]", eid, name); \
46                 gst_object_unref(element[eid].gst); \
47         } \
48         element[eid].id = eid; \
49         element[eid].gst = gst_pipeline_new(name); \
50         if (element[eid].gst == NULL) { \
51                 _mmstreamrec_dbg_err("Pipeline creation fail. element_id=[%d], name=[%s]", eid, name); \
52                 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION; \
53                 goto pipeline_creation_error; \
54         } else { \
55                 g_object_weak_ref(G_OBJECT(element[eid].gst), (GWeakNotify)_mmstreamrecorder_element_release_noti/*NULL*/, sub_context); \
56         }
57
58 #define _MMSTREAMRECORDER_BIN_MAKE(sub_context, element, eid, name /*char* */, err) \
59         if (element[eid].gst != NULL) { \
60                 _mmstreamrec_dbg_err("The element(Bin) is existed. element_id=[%d], name=[%s]", eid, name); \
61                 gst_object_unref(element[eid].gst); \
62         } \
63         element[eid].id = eid; \
64         element[eid].gst = gst_bin_new(name); \
65         if (element[eid].gst == NULL) { \
66                 _mmstreamrec_dbg_err("Bin creation fail. element_id=[%d], name=[%s]\n", eid, name); \
67                 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION; \
68                 goto pipeline_creation_error; \
69         } else { \
70                 g_object_weak_ref(G_OBJECT(element[eid].gst), (GWeakNotify)_mmstreamrecorder_element_release_noti/*NULL*/, sub_context); \
71         }
72
73 #define _MMSTREAMRECORDER_ELEMENT_MAKE(sub_context, element, eid, name /*char* */, nickname /*char* */, elist, err) \
74         if (element[eid].gst != NULL) { \
75                 _mmstreamrec_dbg_err("The element is existed. element_id=[%d], name=[%s]", eid, name); \
76                 gst_object_unref(element[eid].gst); \
77         } \
78         element[eid].gst = gst_element_factory_make(name, nickname); \
79         if (element[eid].gst == NULL) { \
80                 _mmstreamrec_dbg_err("Element creation fail. element_id=[%d], name=[%s]", eid, name); \
81                 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION; \
82                 goto pipeline_creation_error; \
83         } else { \
84                 _mmstreamrec_dbg_err("Element creation done. element_id=[%d], name=[%s]", eid, name); \
85                 element[eid].id = eid; \
86                 g_object_weak_ref(G_OBJECT(element[eid].gst), (GWeakNotify)_mmstreamrecorder_element_release_noti/*NULL*/, sub_context); \
87                 err = MM_ERROR_NONE; \
88         } \
89         elist = g_list_append(elist, &(element[eid]));
90
91 #define _MMSTREAMRECORDER_ELEMENT_MAKE_IGNORE_ERROR(sub_context, element, eid, name /*char* */, nickname /*char* */, elist) \
92         if (element[eid].gst != NULL) { \
93                 _mmstreamrec_dbg_err("The element is existed. element_id=[%d], name=[%s]", eid, name); \
94                 gst_object_unref(element[eid].gst); \
95         } \
96         element[eid].gst = gst_element_factory_make(name, nickname); \
97         if (element[eid].gst == NULL) { \
98                 _mmstreamrec_dbg_err("Element creation fail. element_id=[%d], name=[%s], but keep going...", eid, name); \
99         } else { \
100                 _mmstreamrec_dbg_err("Element creation done. element_id=[%d], name=[%s]", eid, name); \
101                 element[eid].id = eid; \
102                 g_object_weak_ref(G_OBJECT(element[eid].gst), (GWeakNotify)_mmstreamrecorder_element_release_noti/*NULL*/, sub_context); \
103                 elist = g_list_append(elist, &(element[eid])); \
104         }
105
106 #define _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sub_context, eid, name /*char* */, err) \
107         if (sub_context->encode_element[eid].gst != NULL) { \
108                 _mmstreamrec_dbg_err("The element is existed. element_id=[%d], name=[%s]", eid, name); \
109                 gst_object_unref(sub_context->encode_element[eid].gst); \
110         } \
111         sub_context->encode_element[eid].id = eid; \
112         g_object_get(G_OBJECT(sub_context->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst), name, &(sub_context->encode_element[eid].gst), NULL); \
113         if (sub_context->encode_element[eid].gst == NULL) { \
114                 _mmstreamrec_dbg_err("Encode Element get fail. element_id=[%d], name=[%s]", eid, name); \
115                 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION; \
116                 goto pipeline_creation_error; \
117         } else{ \
118                 gst_object_unref(sub_context->encode_element[eid].gst); \
119                 g_object_weak_ref(G_OBJECT(sub_context->encode_element[eid].gst), (GWeakNotify)_mmstreamrecorder_element_release_noti/*NULL*/, sub_context); \
120         }
121
122 /* GStreamer element remove macro */
123 #define _MMSTREAMRECORDER_ELEMENT_REMOVE(element, eid) \
124         do { \
125                 if (element[eid].gst != NULL) { \
126                         gst_object_unref(element[eid].gst); \
127                 } \
128         } while (0)
129
130 #define _MM_GST_ELEMENT_LINK_MANY       gst_element_link_many
131 #define _MM_GST_ELEMENT_LINK            gst_element_link
132 #define _MM_GST_PAD_LINK                gst_pad_link
133
134 #define _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, if_fail_goto)\
135 {\
136         GstPadLinkReturn ret = _MM_GST_PAD_LINK(srcpad, sinkpad);\
137         if (ret != GST_PAD_LINK_OK) {\
138                 GstObject *src_parent = gst_pad_get_parent(srcpad);\
139                 GstObject *sink_parent = gst_pad_get_parent(sinkpad);\
140                 char *src_name = NULL;\
141                 char *sink_name = NULL;\
142                 g_object_get((GObject *)src_parent, "name", &src_name, NULL);\
143                 g_object_get((GObject *)sink_parent, "name", &sink_name, NULL);\
144                 _mmstreamrec_dbg_err("src[%s] - sink[%s] link failed", src_name, sink_name);\
145                 gst_object_unref(src_parent); src_parent = NULL;\
146                 gst_object_unref(sink_parent); sink_parent = NULL;\
147                 if (src_name) {\
148                         free(src_name); src_name = NULL;\
149                 } \
150                 if (sink_name) {\
151                         free(sink_name); sink_name = NULL;\
152                 } \
153                 gst_object_unref(srcpad); srcpad = NULL;\
154                 gst_object_unref(sinkpad); sinkpad = NULL;\
155                 err = MM_ERROR_STREAMRECORDER_GST_LINK;\
156                 goto if_fail_goto;\
157         } \
158         gst_object_unref(srcpad); srcpad = NULL;\
159         gst_object_unref(sinkpad); sinkpad = NULL;\
160 }
161
162 #define _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad) \
163         if (srcpad && sinkpad) { \
164                 gst_pad_unlink(srcpad, sinkpad); \
165         } else { \
166                 _mmstreamrec_dbg_warn("some pad(srcpad:%p,sinkpad:%p) is NULL", srcpad, sinkpad); \
167         } \
168         if (srcpad) { \
169                 gst_object_unref(srcpad); srcpad = NULL; \
170         } \
171         if (sinkpad) { \
172                 gst_object_unref(sinkpad); sinkpad = NULL; \
173         }
174
175 /*=======================================================================================
176 | ENUM DEFINITIONS                                                                      |
177 ========================================================================================*/
178
179 /**
180 * Encodebin profile
181 */
182 typedef enum _MMStreamRecorderEncodebinProfile {
183         MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO = 0,      /**< Video recording profile */
184         MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO,          /**< Audio recording profile */
185         MM_STREAMRECORDER_ENCBIN_PROFILE_IMAGE,          /**< Image capture profile */
186         MM_STREAMRECORDER_ENCBIN_PROFILE_NUM
187 } MMStreamRecorderEncodebinProfile;
188
189 #define __MMSTREAMRECORDER_SET_GST_STATE_TIMEOUT     5
190
191 /*=======================================================================================
192 | STRUCTURE DEFINITIONS                                                                 |
193 ========================================================================================*/
194 /**
195  * Element name table.
196  * @note if name is NULL, not supported.
197  */
198 typedef struct {
199         unsigned int prof_id;   /**< id of mmstreamrecorder_profile_attrs_id */
200         unsigned int id;        /**< id of value id */
201         char *name;             /**< gstreamer element name*/
202 } _MMStreamRecorderElementName;
203
204 /**
205  * MMstreamrecorder Gstreamer Element
206  */
207 typedef struct {
208         unsigned int id;        /**< Gstreamer piplinem element name */
209         GstElement *gst;        /**< Gstreamer element */
210 } _MMStreamRecorderGstElement;
211
212 /*=======================================================================================
213 | CONSTANT DEFINITIONS                                                                  |
214 ========================================================================================*/
215
216 /*=======================================================================================
217 | STATIC VARIABLES                                                                      |
218 ========================================================================================*/
219
220 /*=======================================================================================
221 | EXTERN GLOBAL VARIABLE                                                                |
222 ========================================================================================*/
223
224 /*=======================================================================================
225 | GLOBAL FUNCTION PROTOTYPES                                                            |
226 ========================================================================================*/
227
228 gboolean _mmstreamrecorder_gstreamer_init();
229
230 /* etc */
231 int _mmstreamrecorder_get_eos_message(MMHandleType handle);
232 void _mmstreamrecorder_remove_element_handle(MMHandleType handle, void *element, int first_elem, int last_elem);
233 gboolean _mmstreamrecorder_add_elements_to_bin(GstBin *bin, GList *element_list);
234 gboolean _mmstreamrecorder_link_elements(GList *element_list);
235
236 /**
237  * This function sets gstreamer element status.
238  * If the gstreamer fails to set status or returns asynchronous mode,
239  * this function waits for state changed until timeout expired.
240  *
241  * @param[in]   pipeline        Pointer of pipeline
242  * @param[in]   target_state    newly setting status
243  * @return      This function returns zero on success, or negative value with error code.
244  * @remarks
245  * @see
246  *
247  */
248 int _mmstreamrecorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstState target_state);
249 GstCaps *gst_set_videosrcpad_caps(gint srcfmt, gint width, gint height, gint rate, gint scale);
250 GstCaps *gst_set_audiosrcpad_caps(gint samplerate, gint channel, gint depth, gint width, gint datatype);
251
252 #ifdef __cplusplus
253 }
254 #endif
255 #endif /* __MM_STREAMRECORDER_GSTCOMMON_H__ */