Add new param for setting remote session description and ICE candidiate for WebRTC...
[platform/core/api/mediastreamer.git] / src / media_streamer_util.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <glib/gstdio.h>
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <tizen-extension-client-protocol.h>
21 #include <Ecore_Evas.h>
22 #include <Ecore_Wl2.h>
23 #include "media_streamer.h"
24 #include "media_streamer_priv.h"
25 #include "media_streamer_util.h"
26
27 static const format_s format_table[] = {
28         /* Audio - ENCODED */
29         {MEDIA_FORMAT_L16, "audio/x-raw"},
30         {MEDIA_FORMAT_ALAW, "audio/x-alaw"},
31         {MEDIA_FORMAT_ULAW, "audio/x-mulaw"},
32         {MEDIA_FORMAT_AMR, "audio/AMR"},
33         {MEDIA_FORMAT_AMR_NB, "audio/AMR"},
34         {MEDIA_FORMAT_AMR_WB, "audio/AMR-WB"},
35         {MEDIA_FORMAT_G729, "audio/G729"},
36         {MEDIA_FORMAT_AAC, "audio/mpeg"},
37         {MEDIA_FORMAT_AAC_LC, "audio/mpeg"},
38         {MEDIA_FORMAT_AAC_HE, "audio/mpeg"},
39         {MEDIA_FORMAT_AAC_HE_PS, "audio/mpeg"},
40         {MEDIA_FORMAT_MP3, "audio/mpeg"},
41         /* Audio - RAW */
42         {MEDIA_FORMAT_PCM, "S16LE"},
43         {MEDIA_FORMAT_PCM_S24LE, "S24LE"},
44         {MEDIA_FORMAT_PCM_S32LE, "S32LE"},
45         {MEDIA_FORMAT_PCM_S16BE, "S16BE"},
46         {MEDIA_FORMAT_PCM_S24BE, "S24BE"},
47         {MEDIA_FORMAT_PCM_S32BE, "S32BE"},
48         {MEDIA_FORMAT_PCM_F32LE, "F32LE"},
49         {MEDIA_FORMAT_PCM_F32BE, "F32BE"},
50         /* {MEDIA_FORMAT_PCMA, "audio/x-alaw"}, */
51         /* {MEDIA_FORMAT_PCMU, "audio/x-mulaw"}, */
52         /* Video - ENCODED */
53         {MEDIA_FORMAT_H261, "video/x-h261"},
54         {MEDIA_FORMAT_H263, "video/x-h263"},
55         {MEDIA_FORMAT_H263P, "video/x-h263"},
56         {MEDIA_FORMAT_H264_SP, "video/x-h264"},
57         {MEDIA_FORMAT_H264_MP, "video/x-h264"},
58         {MEDIA_FORMAT_H264_HP, "video/x-h264"},
59         {MEDIA_FORMAT_MJPEG, "image/jpeg"},
60         {MEDIA_FORMAT_MPEG1, "video/mpeg"},
61         {MEDIA_FORMAT_MPEG2_SP, "video/mpeg"},
62         {MEDIA_FORMAT_MPEG2_MP, "video/mpeg"},
63         {MEDIA_FORMAT_MPEG2_HP, "video/mpeg"},
64         {MEDIA_FORMAT_MPEG4_SP, "video/mpeg"},
65         {MEDIA_FORMAT_MPEG4_ASP, "video/mpeg"},
66         {MEDIA_FORMAT_HEVC, "video/x-h265"},
67         {MEDIA_FORMAT_VP8, "video/x-vp8"},
68         {MEDIA_FORMAT_VP9, "video/x-vp9"},
69         {MEDIA_FORMAT_VC1, "video/x-wmv"},
70         /* Video - RAW */
71         {MEDIA_FORMAT_I420, "I420"},
72         {MEDIA_FORMAT_NV12, "NV12"},
73         {MEDIA_FORMAT_NV12T, "NV12T"},
74         {MEDIA_FORMAT_YV12, "YV12"},
75         {MEDIA_FORMAT_NV21, "NV21"},
76         {MEDIA_FORMAT_NV16, "NV16"},
77         {MEDIA_FORMAT_YUYV, "YUYV"},
78         {MEDIA_FORMAT_UYVY, "UYVY"},
79         {MEDIA_FORMAT_422P, "422P"},
80         {MEDIA_FORMAT_RGB565, "RGB565"},
81         {MEDIA_FORMAT_RGB888, "RGB888"},
82         {MEDIA_FORMAT_RGBA, "RGBA"},
83         {MEDIA_FORMAT_ARGB, "ARGB"},
84         {MEDIA_FORMAT_NATIVE_VIDEO, "NATIVE_VIDEO"},
85         /* Container */
86         {MEDIA_FORMAT_CONTAINER_MP4, "video/quicktime"},
87         {MEDIA_FORMAT_CONTAINER_MPEG2TS, "video/mpegts"},
88         {MEDIA_FORMAT_MAX, NULL}
89 };
90
91 static dictionary *__ms_get_ini_instance(void)
92 {
93         static dictionary *instance = NULL;
94         dictionary *ms_dict = NULL;
95
96         ms_debug_fenter();
97
98         if (!instance) {
99                 /* loading existing ini file */
100                 ms_dict = iniparser_load(MEDIA_STREAMER_INI_PATH);
101
102                 if (!ms_dict)
103                         ms_warning("Could not open ini [%s]. Media-streamer will use default values.", MEDIA_STREAMER_INI_PATH);
104                 else
105                         ms_debug("Open ini file [%s].", MEDIA_STREAMER_INI_PATH);
106                 instance = ms_dict;
107         }
108
109         ms_debug_fleave();
110
111         return instance;
112 }
113
114 gchar *ms_ini_get_string(const char *ini_path, const char *default_str)
115 {
116         const char *result_str = default_str;
117
118         ms_debug_fenter();
119
120         ms_retvm_if(ini_path == NULL, NULL, "Invalid ini path");
121
122         if (__ms_get_ini_instance()) {
123                 const char *str = iniparser_getstring(__ms_get_ini_instance(), ini_path, default_str);
124                 if (str && (strlen(str) > 0) && (strlen(str) < INI_MAX_STRLEN))
125                         result_str = str;
126         }
127
128         ms_debug_fleave();
129
130         return g_strdup(result_str);
131 }
132
133 void ms_ini_read_list(const char *key, gchar ***list)
134 {
135         const gchar *str;
136
137         ms_debug_fenter();
138
139         ms_retm_if(!__ms_get_ini_instance() || !list || !key, "Handle is NULL");
140
141         /* Read exclude elements list */
142         str = iniparser_getstring(__ms_get_ini_instance(), key, NULL);
143         if (str && strlen(str) > 0) {
144                 gchar *strtmp = g_strdup(str);
145                 g_strstrip(strtmp);
146
147                 *list = g_strsplit(strtmp, ",", 10);
148                 MS_SAFE_GFREE(strtmp);
149         }
150
151         ms_debug_fleave();
152
153 }
154
155 void ms_load_ini_settings(media_streamer_ini_t *ini)
156 {
157
158         ms_debug_fenter();
159
160         /* get ini values */
161         memset(ini, 0, sizeof(media_streamer_ini_t));
162
163         if (__ms_get_ini_instance()) {
164                 /* general */
165                 ini->generate_dot = iniparser_getboolean(__ms_get_ini_instance(), "general:generate dot", DEFAULT_GENERATE_DOT);
166                 if (ini->generate_dot == TRUE) {
167                         const gchar *dot_path = iniparser_getstring(__ms_get_ini_instance(), "general:dot dir", MEDIA_STREAMER_DEFAULT_DOT_DIR);
168                         ms_debug("generate_dot is TRUE, dot file will be stored into %s", dot_path);
169                         g_setenv("GST_DEBUG_DUMP_DOT_DIR", dot_path, FALSE);
170                 }
171
172                 ini->use_decodebin = iniparser_getboolean(__ms_get_ini_instance(), "general:use decodebin", DEFAULT_USE_DECODEBIN);
173
174                 /* Read exclude elements list */
175                 ms_ini_read_list("general:exclude elements", &ini->exclude_elem_names);
176                 /* Read resource require elements list */
177                 ms_ini_read_list("general:resource elements", &ini->resource_required_elem_names);
178                 /* Read gstreamer arguments list */
179                 ms_ini_read_list("general:gstreamer arguments", &ini->gst_args);
180
181         } else {
182                 /* if dict is not available just fill the structure with default values */
183                 ini->generate_dot = DEFAULT_GENERATE_DOT;
184                 ini->use_decodebin = DEFAULT_USE_DECODEBIN;
185         }
186
187         /* general */
188         ms_debug("Media Streamer param [generate_dot] : %d", ini->generate_dot);
189         ms_debug("Media Streamer param [use_decodebin] : %d", ini->use_decodebin);
190
191         ms_debug_fleave();
192
193 }
194
195 const gchar *ms_convert_mime_to_string_format(media_format_mimetype_e mime)
196 {
197         gchar *format_name = NULL;
198         int it_format;
199
200         ms_debug_fenter();
201
202         for (it_format = 0; format_table[it_format].format != MEDIA_FORMAT_MAX; it_format++) {
203                 if (mime == format_table[it_format].format) {
204                         format_name = format_table[it_format].format_name;
205                         break;
206                 }
207         }
208
209         ms_debug_fleave();
210
211         return format_name;
212 }
213
214 //LCOV_EXCL_START
215 const gchar *ms_convert_mime_to_rtp_format(media_format_mimetype_e mime)
216 {
217         switch (mime) {
218         case MEDIA_FORMAT_I420:
219         case MEDIA_FORMAT_YV12:
220         case MEDIA_FORMAT_ARGB:
221                 return "RAW";
222         case MEDIA_FORMAT_H263:
223                 return "H263";
224         case MEDIA_FORMAT_H264_HP:
225         case MEDIA_FORMAT_H264_MP:
226         case MEDIA_FORMAT_H264_SP:
227                 return "H264";
228         case MEDIA_FORMAT_PCM:
229                 return "L16";
230         default:
231                 ms_error("Invalid or Unsupported media format [%d].", mime);
232                 return NULL;
233         }
234 }
235 //LCOV_EXCL_STOP
236
237 media_format_mimetype_e ms_convert_string_format_to_media_format(const char *format_type)
238 {
239         media_format_mimetype_e mime = MEDIA_FORMAT_NATIVE_VIDEO;
240         int it_format;
241
242         ms_debug_fenter();
243
244         for (it_format = 0; format_table[it_format].format != MEDIA_FORMAT_MAX; it_format++) {
245                 if (g_strrstr(format_type, format_table[it_format].format_name)) {
246                         mime = format_table[it_format].format;
247                         break;
248                 }
249         }
250
251         ms_debug_fleave();
252
253         return mime;
254 }
255
256 void ms_signal_create(GList **sig_list, GstElement *obj, const char *sig_name, GCallback cb, gpointer user_data)
257 {
258         media_streamer_signal_s *sig_data;
259
260         ms_debug_fenter();
261
262         ms_retm_if(!sig_list || !obj || !sig_name, "Empty signal data!");
263
264         sig_data = (media_streamer_signal_s *) g_try_malloc(sizeof(media_streamer_signal_s));
265         if (!sig_data) {
266                 ms_error("Failed to create signal [%s] for object [%s]", sig_name, GST_OBJECT_NAME(obj));
267                 return;
268         }
269
270         sig_data->obj = G_OBJECT(obj);
271         sig_data->signal_id = g_signal_connect(sig_data->obj, sig_name, cb, user_data);
272
273         if (sig_data->signal_id > 0) {
274                 *sig_list = g_list_append(*sig_list, sig_data);
275                 ms_debug("Signal [%s] with id[%lu] connected to object [%s].", sig_name, sig_data->signal_id, GST_OBJECT_NAME(sig_data->obj));
276         } else {
277                 ms_error("Failed to connect signal [%s] for object [%s]", sig_name, GST_OBJECT_NAME(obj));
278                 MS_SAFE_GFREE(sig_data);
279         }
280
281         ms_debug_fleave();
282 }
283
284 void ms_signal_destroy(void *data)
285 {
286         media_streamer_signal_s *sig_data = (media_streamer_signal_s *) data;
287
288         ms_debug_fenter();
289
290         ms_retm_if(!sig_data, "Empty signal data!");
291
292         if (GST_IS_ELEMENT(sig_data->obj)) {
293                 if (g_signal_handler_is_connected(sig_data->obj, sig_data->signal_id)) {
294                         g_signal_handler_disconnect(sig_data->obj, sig_data->signal_id);
295                         ms_debug("Signal with id[%lu] disconnected from object [%s].", sig_data->signal_id, GST_OBJECT_NAME(sig_data->obj));
296                 }
297         }
298         MS_SAFE_GFREE(sig_data);
299
300         ms_debug_fleave();
301 }
302
303 void ms_param_value_destroy(gpointer data)
304 {
305         GValue *val = (GValue *)data;
306
307         ms_debug_fenter();
308
309         ms_retm_if(!data, "Empty object data!");
310
311         if (GST_VALUE_HOLDS_CAPS(val)) {
312                 gst_caps_unref(GST_CAPS(gst_value_get_caps(val)));
313
314                 g_value_reset(val);
315                 g_value_unset(val);
316         }
317         MS_SAFE_GFREE(val);
318
319         ms_debug_fleave();
320 }
321
322 int ms_util_uri_path_check(const char *file_uri)
323 {
324         struct stat stat_results = {0, };
325         int file_open = 0;
326         char mes_error[256];
327         int errnum = 0;
328
329         ms_debug_fenter();
330
331         if (!file_uri || !strlen(file_uri))
332                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
333
334         file_open = open(file_uri, O_RDONLY);
335         if (file_open < 0) {
336                 errnum = errno;
337                 strerror_r(errnum, mes_error, sizeof(mes_error));
338                 ms_error("Couldn`t open file [%s] according to [%s]. Error N [%d]", file_uri, mes_error, errnum);
339
340                 if (EACCES == errnum)
341                         return MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
342
343                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
344         }
345
346         if (fstat(file_open, &stat_results) < 0) {
347                 ms_error("Couldn`t get status of the file [%s]", file_uri);
348         } else if (stat_results.st_size == 0) {
349                 ms_error("The size of file is 0");
350                 close(file_open);
351                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
352         } else {
353                 ms_debug("Size of file [%lld] bytes", (long long)stat_results.st_size);
354         }
355
356         close(file_open);
357
358         ms_debug_fleave();
359
360         return MEDIA_STREAMER_ERROR_NONE;
361 }
362
363 int ms_bin_foreach_elements(GstBin *bin, GstIteratorFoldFunction func, void *user_data)
364 {
365         media_streamer_s *streamer = (media_streamer_s *) user_data;
366
367         ms_debug_fenter();
368
369         if (!GST_BIN_NUMCHILDREN(bin)) {
370                 ms_debug("No elements were added to bin [%s]. Skipping... ",
371                         GST_ELEMENT_NAME(bin));
372                 return MEDIA_STREAMER_STATE_NONE;
373         }
374
375         GstIterator *iter = gst_bin_iterate_recurse(bin);
376         GValue ret = G_VALUE_INIT;
377         GstIteratorResult result = GST_ITERATOR_DONE;
378
379         g_value_init(&ret, G_TYPE_BOOLEAN);
380         result = gst_iterator_fold(iter, func, &ret, streamer);
381         gst_iterator_free(iter);
382
383         switch (result) {
384         case GST_ITERATOR_RESYNC:
385         case GST_ITERATOR_ERROR:
386                 ms_error("Error while iterating elements in bin [%s]!",
387                         GST_ELEMENT_NAME(bin));
388                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
389                 break;
390         case GST_ITERATOR_DONE:
391         case GST_ITERATOR_OK:
392                 /* Check for last return value */
393                 if (!g_value_get_boolean(&ret)) {
394                         ms_error("Failed to prepare one of nodes");
395                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
396                 }
397                 break;
398         default:
399                 break;
400         }
401
402         ms_debug_fleave();
403
404         return MEDIA_STREAMER_ERROR_NONE;
405 }
406
407 /* Use g_free() to free the return value. */
408 gchar* ms_get_string_from_json_object(JsonObject *object)
409 {
410         JsonNode *root;
411         JsonGenerator *generator;
412         gchar *text;
413
414         ms_retvm_if(object == NULL, NULL, "object is NULL");
415
416         root = json_node_init_object(json_node_alloc(), object);
417         generator = json_generator_new();
418         json_generator_set_root(generator, root);
419         text = json_generator_to_data(generator, NULL);
420
421         g_object_unref(generator);
422         json_node_free(root);
423
424         return text;
425 }
426
427 /* Use g_free() to free the sdp and type parameter. */
428 int ms_webrtc_get_sdp_from_message(const char *sdp_msg, gchar **sdp, gchar **type)
429 {
430         int ret = MEDIA_STREAMER_ERROR_NONE;
431         JsonNode *root;
432         JsonObject *object;
433         JsonObject *child;
434         JsonParser *parser;
435         const gchar *member_sdp;
436         const gchar *member_type;
437
438         ms_retvm_if(sdp_msg == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "sdp_msg is NULL");
439         ms_retvm_if(sdp == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "sdp is NULL");
440
441         parser = json_parser_new();
442         if (!JSON_IS_PARSER(parser))
443                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
444
445         if (!json_parser_load_from_data(parser, sdp_msg, -1, NULL)) {
446                 ms_error("Unknown message: %s", sdp_msg);
447                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
448                 goto end;
449         }
450
451         root = json_parser_get_root(parser);
452         if (!JSON_NODE_HOLDS_OBJECT(root)) {
453                 ms_error("It does not contain a JsonObject: %s", sdp_msg);
454                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
455                 goto end;
456         }
457
458         object = json_node_get_object(root);
459         if (!json_object_has_member(object, "sdp")) {
460                 ms_error("It does not contain 'sdp' member: %s", sdp_msg);
461                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
462                 goto end;
463         }
464
465         child = json_object_get_object_member(object, "sdp");
466
467         member_type = json_object_get_string_member(child, "type");
468         if (!member_type || !(g_str_equal(member_type, "answer") || g_str_equal(member_type, "offer"))) {
469                 ms_error("Could not find valid type member: %s", sdp_msg);
470                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
471                 goto end;
472         }
473         *type = g_strdup(member_type);
474
475         member_sdp = json_object_get_string_member(child, "sdp");
476         if (!member_sdp) {
477                 ms_error("Could not find sdb member: %s", sdp_msg);
478                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
479                 goto end;
480         }
481
482         *sdp = g_strdup(member_sdp);
483
484         ms_info("type: %s", *type);
485         ms_info("sdp:\n%s", *sdp);
486 end:
487         g_object_unref (parser);
488         return ret;
489 }
490
491 /* Use g_free() to free the candidate parameter. */
492 int ms_webrtc_get_ice_candidate_from_message(const char *ice_msg, gchar **candidate, gint *mlineindex)
493 {
494         int ret = MEDIA_STREAMER_ERROR_NONE;
495         JsonNode *root;
496         JsonObject *object;
497         JsonObject *child;
498         JsonParser *parser;
499         const gchar *_candidate;
500
501         ms_retvm_if(ice_msg == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ice_msg is NULL");
502         ms_retvm_if(candidate == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "candidate is NULL");
503         ms_retvm_if(mlineindex == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "mlineindex is NULL");
504
505         parser = json_parser_new();
506         if (!JSON_IS_PARSER(parser))
507                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
508
509         if (!json_parser_load_from_data(parser, ice_msg, -1, NULL)) {
510                 ms_error("Unknown message: %s", ice_msg);
511                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
512                 goto end;
513         }
514
515         root = json_parser_get_root(parser);
516         if (!JSON_NODE_HOLDS_OBJECT(root)) {
517                 ms_error("It does not contain a JsonObject: %s", ice_msg);
518                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
519                 goto end;
520         }
521
522         object = json_node_get_object(root);
523         if (!json_object_has_member(object, "ice")) {
524                 ms_error("It does not contain 'ice' member: %s", ice_msg);
525                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
526                 goto end;
527         }
528
529         child = json_object_get_object_member(object, "ice");
530
531         _candidate = json_object_get_string_member(child, "candidate");
532         if (!_candidate) {
533                 ms_error("Could not find candidate member: %s", ice_msg);
534                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
535                 goto end;
536         }
537
538         *candidate = g_strdup(_candidate);
539         *mlineindex = json_object_get_int_member(child, "sdpMLineIndex");
540
541         ms_debug("candidate: %s", *candidate);
542         ms_debug("sdpMLineIndex: %d", *mlineindex);
543 end:
544         g_object_unref(parser);
545         return ret;
546 }
547
548 //LCOV_EXCL_START
549 static void __global(void *data, struct wl_registry *registry,
550         uint32_t name, const char *interface, uint32_t version)
551 {
552         struct tizen_surface **tz_surface = NULL;
553
554         if (!data) {
555                 LOGE("NULL data");
556                 return;
557         }
558
559         tz_surface = (struct tizen_surface **)data;
560
561         if (!interface) {
562                 LOGW("NULL interface");
563                 return;
564         }
565
566         if (strcmp(interface, "tizen_surface") == 0) {
567                 LOGD("binding tizen surface for wayland");
568
569                 *tz_surface = wl_registry_bind(registry, name, &tizen_surface_interface, 1);
570                 if (*tz_surface == NULL)
571                         LOGE("failed to bind");
572
573                 LOGD("done");
574         }
575
576         return;
577 }
578
579 static void __global_remove(void *data, struct wl_registry *wl_registry, uint32_t name)
580 {
581         LOGD("enter");
582         return;
583 }
584
585 static const struct wl_registry_listener _media_streamer_wl_registry_listener = {
586         __global,
587         __global_remove
588 };
589
590 static void __parent_id_getter(void *data, struct tizen_resource *tizen_resource, uint32_t id)
591 {
592         if (!data) {
593                 LOGE("NULL data");
594                 return;
595         }
596
597         *((unsigned int *)data) = id;
598
599         LOGD("[CLIENT] got parent_id [%u] from server", id);
600
601         return;
602 }
603
604 static const struct tizen_resource_listener _media_streamer_tz_resource_listener = {
605         __parent_id_getter
606 };
607
608 int ms_get_wl_info(Evas_Object *obj, media_streamer_wl_info_s *wl_info)
609 {
610         int ret = MEDIA_STREAMER_ERROR_NONE;
611         Ecore_Wl2_Window *window = NULL;
612         Ecore_Evas *ee = NULL;
613         Ecore_Wl2_Display *e_wl2_display = NULL;
614         Evas *e = NULL;
615         struct wl_display *display = NULL;
616         struct wl_display *display_wrapper = NULL;
617         struct wl_surface *surface = NULL;
618         struct wl_registry *registry = NULL;
619         struct wl_event_queue *queue = NULL;
620         struct tizen_surface *tz_surface = NULL;
621         struct tizen_resource *tz_resource = NULL;
622
623         if (!obj || !wl_info) {
624                 LOGE("NULL parameter %p %p", obj, wl_info);
625                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
626         }
627
628         e = evas_object_evas_get(obj);
629         if (!e) {
630                 LOGE("failed to get evas object");
631                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
632                 goto _DONE;
633         }
634
635         ee = ecore_evas_ecore_evas_get(e);
636         if (!ee) {
637                 LOGE("failed to get ecore evas object");
638                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
639                 goto _DONE;
640         }
641
642         window = ecore_evas_wayland2_window_get(ee);
643         if (!window) {
644                 LOGE("failed to get wayland window");
645                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
646                 goto _DONE;
647         }
648
649         /* set video_has flag to a video application window */
650         ecore_wl2_window_video_has(window, EINA_TRUE);
651
652         surface = (struct wl_surface *)ecore_wl2_window_surface_get(window);
653         if (!surface) {
654                 LOGE("failed to get wayland surface");
655                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
656                 goto _DONE;
657         }
658
659         e_wl2_display = ecore_wl2_connected_display_get(NULL);
660         if (!e_wl2_display) {
661                 LOGE("failed to get ecore wl2 display");
662                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
663                 goto _DONE;
664         }
665
666         display = (struct wl_display *)ecore_wl2_display_get(e_wl2_display);
667         if (!display) {
668                 LOGE("failed to get wayland display");
669                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
670                 goto _DONE;
671         }
672
673         display_wrapper = wl_proxy_create_wrapper(display);
674         if (!display_wrapper) {
675                 LOGE("failed to create wl display wrapper");
676                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
677                 goto _DONE;
678         }
679
680         queue = wl_display_create_queue(display);
681         if (!queue) {
682                 LOGE("failed to create wl display queue");
683                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
684                 goto _DONE;
685         }
686
687         wl_proxy_set_queue((struct wl_proxy *)display_wrapper, queue);
688
689         registry = wl_display_get_registry(display_wrapper);
690         if (!registry) {
691                 LOGE("failed to get wayland registry");
692                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
693                 goto _DONE;
694         }
695
696         wl_registry_add_listener(registry, &_media_streamer_wl_registry_listener, &tz_surface);
697
698         wl_display_dispatch_queue(display, queue);
699         wl_display_roundtrip_queue(display, queue);
700
701         if (!tz_surface) {
702                 LOGE("failed to get tizen surface");
703                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
704                 goto _DONE;
705         }
706
707         tz_resource = tizen_surface_get_tizen_resource(tz_surface, surface);
708         if (!tz_resource) {
709                 LOGE("failed to get tizen resource");
710                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
711                 goto _DONE;
712         }
713
714         wl_info->parent_id = 0;
715
716         tizen_resource_add_listener(tz_resource, &_media_streamer_tz_resource_listener, &wl_info->parent_id);
717
718         wl_display_roundtrip_queue(display, queue);
719
720         if (wl_info->parent_id > 0) {
721                 LOGD("parent id : %u", wl_info->parent_id);
722         } else {
723                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
724                 LOGE("failed to get parent id");
725         }
726
727 _DONE:
728         if (tz_surface) {
729                 tizen_surface_destroy(tz_surface);
730                 tz_surface = NULL;
731         }
732
733         if (tz_resource) {
734                 tizen_resource_destroy(tz_resource);
735                 tz_resource = NULL;
736         }
737
738         if (registry) {
739                 wl_registry_destroy(registry);
740                 registry = NULL;
741         }
742
743         if (queue) {
744                 wl_event_queue_destroy(queue);
745                 queue = NULL;
746         }
747
748         if (display_wrapper) {
749                 wl_proxy_wrapper_destroy(display_wrapper);
750                 display_wrapper = NULL;
751         }
752
753         return ret;
754 }
755 //LCOV_EXCL_STOP