4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hyuntae Kim <ht1211.kim@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 =======================================================================================*/
28 #include "mm_streamrecorder_internal.h"
29 #include "mm_streamrecorder_gstcommon.h"
30 #include "mm_streamrecorder_gstdispatch.h"
31 #include "mm_streamrecorder_util.h"
32 #include "mm_streamrecorder.h"
34 /*-----------------------------------------------------------------------
35 | GLOBAL VARIABLE DEFINITIONS for internal |
36 -----------------------------------------------------------------------*/
38 /*-----------------------------------------------------------------------
39 | LOCAL VARIABLE DEFINITIONS for internal |
40 -----------------------------------------------------------------------*/
41 #define USE_AUDIO_CLOCK_TUNE
42 #define _MMSTREAMRECORDER_WAIT_EOS_TIME 5.0 /* sec */
43 #define _MMSTREAMRECORDER_STATE_SET_COUNT 3
45 /*-----------------------------------------------------------------------
46 | LOCAL FUNCTION PROTOTYPES: |
47 -----------------------------------------------------------------------*/
48 /* STATIC INTERNAL FUNCTION */
50 /*=======================================================================================
51 | FUNCTION DEFINITIONS |
52 =======================================================================================*/
53 /*-----------------------------------------------------------------------
54 | GLOBAL FUNCTION DEFINITIONS: |
55 -----------------------------------------------------------------------*/
56 gboolean _mmstreamrecorder_gstreamer_init()
58 static const int max_argc = 10;
64 /* type_string_array *GSTInitOption = NULL; */
66 /* mmf_return_val_if_fail(conf, FALSE); */
68 _mmstreamrec_dbg_log("");
71 argc = malloc(sizeof(int));
72 argv = malloc(sizeof(gchar *) * max_argc);
77 memset(argv, 0, sizeof(gchar *) * max_argc);
81 argv[0] = g_strdup("mmstreamrecorder");
83 _mmstreamrec_dbg_log("initializing gstreamer with following parameter[argc:%d]", *argc);
85 for (i = 0; i < *argc; i++)
86 _mmstreamrec_dbg_log("argv[%d] : %s", i, argv[i]);
88 /* initializing gstreamer */
89 ret = gst_init_check(argc, &argv, &err);
92 _mmstreamrec_dbg_err("Could not initialize GStreamer: %s ", err ? err->message : "unknown error occurred");
99 for (i = 0; i < *argc; i++) {
119 _mmstreamrec_dbg_err("failed to initialize gstreamer");
134 int _mmstreamrecorder_get_eos_message(MMHandleType handle)
136 double elapsed = 0.0;
138 GstMessage *gMessage = NULL;
140 GstClockTime timeout = 1 * GST_SECOND; /* maximum waiting time */
141 GTimer *timer = NULL;
143 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
144 _MMStreamRecorderSubContext *sc = NULL;
146 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
147 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
149 _mmstreamrec_dbg_log("");
151 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
152 timer = g_timer_new();
154 if (!(sc->bget_eos)) {
156 elapsed = g_timer_elapsed(timer, NULL);
158 /*_mmstreamrec_dbg_log("elapsed:%f sec", elapsed);*/
160 if (elapsed > _MMSTREAMRECORDER_WAIT_EOS_TIME) {
161 _mmstreamrec_dbg_warn("Timeout. EOS isn't received.");
162 g_timer_destroy(timer);
163 gst_object_unref(bus);
164 return MM_ERROR_STREAMRECORDER_RESPONSE_TIMEOUT;
167 gMessage = gst_bus_timed_pop(bus, timeout);
168 if (gMessage != NULL) {
169 _mmstreamrec_dbg_log("Get message(%x).", GST_MESSAGE_TYPE(gMessage));
170 _mmstreamrecorder_pipeline_cb_message(bus, gMessage, (void *)hstreamrecorder);
172 if (GST_MESSAGE_TYPE(gMessage) == GST_MESSAGE_EOS || sc->bget_eos) {
173 gst_message_unref(gMessage);
176 gst_message_unref(gMessage);
178 _mmstreamrec_dbg_log("timeout of gst_bus_timed_pop()");
180 _mmstreamrec_dbg_log("Get EOS in another thread.");
187 g_timer_destroy(timer);
189 gst_object_unref(bus);
192 _mmstreamrec_dbg_err("subcontext error NULL");
194 _mmstreamrec_dbg_log("END");
196 return MM_ERROR_NONE;
199 void _mmstreamrecorder_remove_element_handle(MMHandleType handle, void *element, int first_elem, int last_elem)
202 _MMStreamRecorderGstElement *remove_element = (_MMStreamRecorderGstElement *) element;
204 mmf_return_if_fail(handle && remove_element);
205 mmf_return_if_fail((first_elem >= 0) && (last_elem > 0) && (last_elem > first_elem));
207 _mmstreamrec_dbg_log("");
209 for (i = first_elem; i <= last_elem; i++) {
210 remove_element[i].gst = NULL;
211 remove_element[i].id = _MMSTREAMRECORDER_ENCODE_NONE;
217 gboolean _mmstreamrecorder_add_elements_to_bin(GstBin *bin, GList *element_list)
219 GList *local_list = element_list;
220 _MMStreamRecorderGstElement *element = NULL;
222 mmf_return_val_if_fail(bin && local_list, FALSE);
225 element = (_MMStreamRecorderGstElement *) local_list->data;
226 if (element && element->gst) {
227 if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
228 _mmstreamrec_dbg_err("Add element [%s] to bin [%s] FAILED", GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), GST_ELEMENT_NAME(GST_ELEMENT(bin)));
231 _mmstreamrec_dbg_log("Add element [%s] to bin [%s] OK", GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), GST_ELEMENT_NAME(GST_ELEMENT(bin)));
234 local_list = local_list->next;
240 gboolean _mmstreamrecorder_link_elements(GList * element_list)
242 GList *local_list = element_list;
243 _MMStreamRecorderGstElement *element = NULL;
244 _MMStreamRecorderGstElement *pre_element = NULL;
246 mmf_return_val_if_fail(local_list, FALSE);
248 pre_element = (_MMStreamRecorderGstElement *) local_list->data;
249 local_list = local_list->next;
252 element = (_MMStreamRecorderGstElement *) local_list->data;
253 if (element && element->gst) {
254 if (pre_element != NULL) {
255 if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(pre_element->gst), GST_ELEMENT(element->gst))) {
256 _mmstreamrec_dbg_log("Link [%s] to [%s] OK", GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)), GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
258 _mmstreamrec_dbg_err("Link [%s] to [%s] FAILED", GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)), GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
262 _mmstreamrec_dbg_err("pre_element is null");
267 pre_element = element;
268 local_list = local_list->next;
274 int _mmstreamrecorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstState target_state)
277 GstState pipeline_state = GST_STATE_VOID_PENDING;
278 GstStateChangeReturn setChangeReturn = GST_STATE_CHANGE_FAILURE;
279 GstStateChangeReturn getChangeReturn = GST_STATE_CHANGE_FAILURE;
280 GstClockTime get_timeout = __MMSTREAMRECORDER_SET_GST_STATE_TIMEOUT * GST_SECOND;
282 mmf_return_val_if_fail(handle, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
284 _mmstreamrec_dbg_log("Set state to %d", target_state);
286 _MMSTREAMRECORDER_LOCK_GST_STATE(handle);
288 for (k = 0; k < _MMSTREAMRECORDER_STATE_SET_COUNT; k++) {
289 setChangeReturn = gst_element_set_state(pipeline, target_state);
290 _mmstreamrec_dbg_log("gst_element_set_state[%d] return %d", target_state, setChangeReturn);
291 if (setChangeReturn != GST_STATE_CHANGE_FAILURE) {
292 getChangeReturn = gst_element_get_state(pipeline, &pipeline_state, NULL, get_timeout);
293 switch (getChangeReturn) {
294 case GST_STATE_CHANGE_NO_PREROLL:
295 _mmstreamrec_dbg_log("status=GST_STATE_CHANGE_NO_PREROLL.");
296 case GST_STATE_CHANGE_SUCCESS:
297 /* if we reached the final target state, exit */
298 if (pipeline_state == target_state) {
299 _MMSTREAMRECORDER_UNLOCK_GST_STATE(handle);
300 return MM_ERROR_NONE;
303 case GST_STATE_CHANGE_ASYNC:
304 _mmstreamrec_dbg_log("status=GST_STATE_CHANGE_ASYNC.");
307 _MMSTREAMRECORDER_UNLOCK_GST_STATE(handle);
308 _mmstreamrec_dbg_log("status=GST_STATE_CHANGE_FAILURE.");
309 return MM_ERROR_STREAMRECORDER_GST_STATECHANGE;
312 _MMSTREAMRECORDER_UNLOCK_GST_STATE(handle);
313 _mmstreamrec_dbg_err("timeout of gst_element_get_state()!!");
314 return MM_ERROR_STREAMRECORDER_RESPONSE_TIMEOUT;
316 usleep(_MMSTREAMRECORDER_STATE_CHECK_INTERVAL);
319 _MMSTREAMRECORDER_UNLOCK_GST_STATE(handle);
321 _mmstreamrec_dbg_err("Failure. gst_element_set_state timeout!!");
323 return MM_ERROR_STREAMRECORDER_RESPONSE_TIMEOUT;
326 GstCaps *gst_set_videosrcpad_caps(gint srcfmt, gint width, gint height, gint rate, gint scale)
329 GstCaps *caps = NULL;
331 if (srcfmt == MM_STREAMRECORDER_INPUT_FORMAT_NV12)
332 caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL);
333 else if (srcfmt == MM_STREAMRECORDER_INPUT_FORMAT_I420)
334 caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "I420", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL);
336 caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "BGRA8888", "bpp", G_TYPE_INT, 32, "depth", G_TYPE_INT, 24, "endianness", G_TYPE_INT, 4321, "red_mask", G_TYPE_INT, 65280, "green_mask", G_TYPE_INT, 16711680, "blue_mask", G_TYPE_INT, -16777216, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL);
339 _mmstreamrec_dbg_err("failed to alloc caps");
343 /* gchar *type = gst_caps_to_string(caps); */
345 /* _mmstreamrec_dbg_warn("Set srcpad caps: %s",type); */
352 GstCaps *gst_set_audiosrcpad_caps(gint samplerate, gint channel, gint depth, gint width, gint datatype)
355 GstCaps *caps = gst_caps_new_simple("audio/x-raw",
356 "rate", G_TYPE_INT, samplerate,
357 "channels", G_TYPE_INT, 2,
358 "depth", G_TYPE_INT, depth,
359 "width", G_TYPE_INT, width,
360 "signed", G_TYPE_BOOLEAN, TRUE,
361 "endianness", G_TYPE_INT, 1234,
365 _mmstreamrec_dbg_err("failed to alloc caps");
369 /* gchar *type = gst_caps_to_string(caps); */
371 /* _mmstreamrec_dbg_log("Set srcpad caps: %s", type); */