44c71f2c36c4bb3f3d6016e9d3483edfb8ae3868
[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 parameter. */
428 int ms_webrtc_get_sdp_from_message(const char *sdp_msg, gchar **sdp)
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
474         member_sdp = json_object_get_string_member(child, "sdp");
475         if (!member_sdp) {
476                 ms_error("Could not find sdb member: %s", sdp_msg);
477                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
478                 goto end;
479         }
480
481         *sdp = g_strdup(member_sdp);
482
483         ms_debug("sdp: %s", *sdp);
484 end:
485         g_object_unref (parser);
486         return ret;
487 }
488
489 /* Use g_free() to free the candidate parameter. */
490 int ms_webrtc_get_ice_candidate_from_message(const char *ice_msg, gchar **candidate, gint *mlineindex)
491 {
492         int ret = MEDIA_STREAMER_ERROR_NONE;
493         JsonNode *root;
494         JsonObject *object;
495         JsonObject *child;
496         JsonParser *parser;
497         const gchar *_candidate;
498
499         ms_retvm_if(ice_msg == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ice_msg is NULL");
500         ms_retvm_if(candidate == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "candidate is NULL");
501         ms_retvm_if(mlineindex == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "mlineindex is NULL");
502
503         parser = json_parser_new();
504         if (!JSON_IS_PARSER(parser))
505                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
506
507         if (!json_parser_load_from_data(parser, ice_msg, -1, NULL)) {
508                 ms_error("Unknown message: %s", ice_msg);
509                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
510                 goto end;
511         }
512
513         root = json_parser_get_root(parser);
514         if (!JSON_NODE_HOLDS_OBJECT(root)) {
515                 ms_error("It does not contain a JsonObject: %s", ice_msg);
516                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
517                 goto end;
518         }
519
520         object = json_node_get_object(root);
521         if (!json_object_has_member(object, "ice")) {
522                 ms_error("It does not contain 'ice' member: %s", ice_msg);
523                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
524                 goto end;
525         }
526
527         child = json_object_get_object_member(object, "ice");
528
529         _candidate = json_object_get_string_member(child, "candidate");
530         if (!_candidate) {
531                 ms_error("Could not find candidate member: %s", ice_msg);
532                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
533                 goto end;
534         }
535
536         *candidate = g_strdup(_candidate);
537         *mlineindex = json_object_get_int_member(child, "sdpMLineIndex");
538
539         ms_debug("candidate: %s", *candidate);
540         ms_debug("sdpMLineIndex: %d", *mlineindex);
541 end:
542         g_object_unref(parser);
543         return ret;
544 }
545
546 //LCOV_EXCL_START
547 static void __global(void *data, struct wl_registry *registry,
548         uint32_t name, const char *interface, uint32_t version)
549 {
550         struct tizen_surface **tz_surface = NULL;
551
552         if (!data) {
553                 LOGE("NULL data");
554                 return;
555         }
556
557         tz_surface = (struct tizen_surface **)data;
558
559         if (!interface) {
560                 LOGW("NULL interface");
561                 return;
562         }
563
564         if (strcmp(interface, "tizen_surface") == 0) {
565                 LOGD("binding tizen surface for wayland");
566
567                 *tz_surface = wl_registry_bind(registry, name, &tizen_surface_interface, 1);
568                 if (*tz_surface == NULL)
569                         LOGE("failed to bind");
570
571                 LOGD("done");
572         }
573
574         return;
575 }
576
577 static void __global_remove(void *data, struct wl_registry *wl_registry, uint32_t name)
578 {
579         LOGD("enter");
580         return;
581 }
582
583 static const struct wl_registry_listener _media_streamer_wl_registry_listener = {
584         __global,
585         __global_remove
586 };
587
588 static void __parent_id_getter(void *data, struct tizen_resource *tizen_resource, uint32_t id)
589 {
590         if (!data) {
591                 LOGE("NULL data");
592                 return;
593         }
594
595         *((unsigned int *)data) = id;
596
597         LOGD("[CLIENT] got parent_id [%u] from server", id);
598
599         return;
600 }
601
602 static const struct tizen_resource_listener _media_streamer_tz_resource_listener = {
603         __parent_id_getter
604 };
605
606 int ms_get_wl_info(Evas_Object *obj, media_streamer_wl_info_s *wl_info)
607 {
608         int ret = MEDIA_STREAMER_ERROR_NONE;
609         Ecore_Wl2_Window *window = NULL;
610         Ecore_Evas *ee = NULL;
611         Ecore_Wl2_Display *e_wl2_display = NULL;
612         Evas *e = NULL;
613         struct wl_display *display = NULL;
614         struct wl_display *display_wrapper = NULL;
615         struct wl_surface *surface = NULL;
616         struct wl_registry *registry = NULL;
617         struct wl_event_queue *queue = NULL;
618         struct tizen_surface *tz_surface = NULL;
619         struct tizen_resource *tz_resource = NULL;
620
621         if (!obj || !wl_info) {
622                 LOGE("NULL parameter %p %p", obj, wl_info);
623                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
624         }
625
626         e = evas_object_evas_get(obj);
627         if (!e) {
628                 LOGE("failed to get evas object");
629                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
630                 goto _DONE;
631         }
632
633         ee = ecore_evas_ecore_evas_get(e);
634         if (!ee) {
635                 LOGE("failed to get ecore evas object");
636                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
637                 goto _DONE;
638         }
639
640         window = ecore_evas_wayland2_window_get(ee);
641         if (!window) {
642                 LOGE("failed to get wayland window");
643                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
644                 goto _DONE;
645         }
646
647         /* set video_has flag to a video application window */
648         ecore_wl2_window_video_has(window, EINA_TRUE);
649
650         surface = (struct wl_surface *)ecore_wl2_window_surface_get(window);
651         if (!surface) {
652                 LOGE("failed to get wayland surface");
653                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
654                 goto _DONE;
655         }
656
657         e_wl2_display = ecore_wl2_connected_display_get(NULL);
658         if (!e_wl2_display) {
659                 LOGE("failed to get ecore wl2 display");
660                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
661                 goto _DONE;
662         }
663
664         display = (struct wl_display *)ecore_wl2_display_get(e_wl2_display);
665         if (!display) {
666                 LOGE("failed to get wayland display");
667                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
668                 goto _DONE;
669         }
670
671         display_wrapper = wl_proxy_create_wrapper(display);
672         if (!display_wrapper) {
673                 LOGE("failed to create wl display wrapper");
674                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
675                 goto _DONE;
676         }
677
678         queue = wl_display_create_queue(display);
679         if (!queue) {
680                 LOGE("failed to create wl display queue");
681                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
682                 goto _DONE;
683         }
684
685         wl_proxy_set_queue((struct wl_proxy *)display_wrapper, queue);
686
687         registry = wl_display_get_registry(display_wrapper);
688         if (!registry) {
689                 LOGE("failed to get wayland registry");
690                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
691                 goto _DONE;
692         }
693
694         wl_registry_add_listener(registry, &_media_streamer_wl_registry_listener, &tz_surface);
695
696         wl_display_dispatch_queue(display, queue);
697         wl_display_roundtrip_queue(display, queue);
698
699         if (!tz_surface) {
700                 LOGE("failed to get tizen surface");
701                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
702                 goto _DONE;
703         }
704
705         tz_resource = tizen_surface_get_tizen_resource(tz_surface, surface);
706         if (!tz_resource) {
707                 LOGE("failed to get tizen resource");
708                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
709                 goto _DONE;
710         }
711
712         wl_info->parent_id = 0;
713
714         tizen_resource_add_listener(tz_resource, &_media_streamer_tz_resource_listener, &wl_info->parent_id);
715
716         wl_display_roundtrip_queue(display, queue);
717
718         if (wl_info->parent_id > 0) {
719                 LOGD("parent id : %u", wl_info->parent_id);
720         } else {
721                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
722                 LOGE("failed to get parent id");
723         }
724
725 _DONE:
726         if (tz_surface) {
727                 tizen_surface_destroy(tz_surface);
728                 tz_surface = NULL;
729         }
730
731         if (tz_resource) {
732                 tizen_resource_destroy(tz_resource);
733                 tz_resource = NULL;
734         }
735
736         if (registry) {
737                 wl_registry_destroy(registry);
738                 registry = NULL;
739         }
740
741         if (queue) {
742                 wl_event_queue_destroy(queue);
743                 queue = NULL;
744         }
745
746         if (display_wrapper) {
747                 wl_proxy_wrapper_destroy(display_wrapper);
748                 display_wrapper = NULL;
749         }
750
751         return ret;
752 }
753 //LCOV_EXCL_STOP