ACLOCAL_AMFLAGS='-I m4'
-SUBDIRS = common sink
+SUBDIRS = src
pcfiles = mm-wfd.pc
pkgconfigdir = $(libdir)/pkgconfig
+++ /dev/null
-lib_LTLIBRARIES = libwfdcommon.la
-
-includelibwfdcommondir = $(includedir)/mmf
-
-libwfdcommon_la_SOURCES = mm_wfd_attrs.c mm_wfd_sink_ini.c
-
-libwfdcommon_la_CFLAGS = -I$(srcdir)/include \
- $(GLIB_CFLAGS) \
- $(TZPLATFORM_CONFIG_CFLAGS) \
- $(MMCOMMON_CFLAGS)
-
-libwfdcommon_la_LIBADD = $(GLIB_LIBS) \
- $(MMCOMMON_LIBS) \
- $(TZPLATFORM_CONFIG_LIBS) \
- $(INIPARSER_LIBS)
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef __MM_WFD_ATTRS_H__
-#define __MM_WFD_ATTRS_H__
-
-#include <string.h>
-#include <glib.h>
-#include <mm_message.h>
-#include <mm_error.h>
-#include <mm_types.h>
-#include <mm_attrs_private.h>
-#include <mm_attrs.h>
-#include <mm_debug.h>
-
-/* general */
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-#endif
-#define MMWFD_MAX_INT (2147483647)
-
-/**
- * Enumeration for attribute values types.
- */
-typedef enum {
- MM_WFD_ATTRS_TYPE_INVALID = -1, /**< Type is invalid */
- MM_WFD_ATTRS_TYPE_INT, /**< Integer type */
- MM_WFD_ATTRS_TYPE_DOUBLE, /**< Double type */
- MM_WFD_ATTRS_TYPE_STRING, /**< UTF-8 String type */
- MM_WFD_ATTRS_TYPE_DATA, /**< Pointer type */
- MM_WFD_ATTRS_TYPE_ARRAY, /**< Array type */
- MM_WFD_ATTRS_TYPE_RANGE, /**< Range type */
- MM_WFD_ATTRS_TYPE_NUM, /**< Number of attribute type */
-} MMWfdAttrsType;
-
-/**
- * Enumeration for attribute validation type.
- */
-typedef enum {
- MM_WFD_ATTRS_VALID_TYPE_INVALID = -1, /**< Invalid validation type */
- MM_WFD_ATTRS_VALID_TYPE_NONE, /**< Do not check validity */
- MM_WFD_ATTRS_VALID_TYPE_INT_ARRAY, /**< validity checking type of integer array */
- MM_WFD_ATTRS_VALID_TYPE_INT_RANGE, /**< validity checking type of integer range */
- MM_WFD_ATTRS_VALID_TYPE_DOUBLE_ARRAY, /**< validity checking type of double array */
- MM_WFD_ATTRS_VALID_TYPE_DOUBLE_RANGE, /**< validity checking type of double range */
-} MMWfdAttrsValidType;
-
-/**
- * Enumeration for attribute access flag.
- */
-typedef enum {
- MM_WFD_ATTRS_FLAG_NONE = 0, /**< None flag is set */
- MM_WFD_ATTRS_FLAG_READABLE = 1 << 0, /**< Readable */
- MM_WFD_ATTRS_FLAG_WRITABLE = 1 << 1, /**< Writable */
- MM_WFD_ATTRS_FLAG_MODIFIED = 1 << 2, /**< Modified */
-
- MM_WFD_ATTRS_FLAG_RW = MM_WFD_ATTRS_FLAG_READABLE | MM_WFD_ATTRS_FLAG_WRITABLE, /**< Readable and Writable */
-} MMWfdAttrsFlag;
-
-/**
- * Attribute validity structure
- */
-typedef struct {
- MMWfdAttrsType type;
- MMWfdAttrsValidType validity_type;
- MMWfdAttrsFlag flag;
- /**
- * a union that describes validity of the attribute.
- * Only when type is 'MM_ATTRS_TYPE_INT' or 'MM_ATTRS_TYPE_DOUBLE',
- * the attribute can have validity.
- */
- union {
- /**
- * Validity structure for integer array.
- */
- struct {
- int *array; /**< a pointer of array */
- int count; /**< size of array */
- int d_val;
- } int_array;
- /**
- * Validity structure for integer range.
- */
- struct {
- int min; /**< minimum range */
- int max; /**< maximum range */
- int d_val;
- } int_range;
- /**
- * Validity structure for double array.
- */
- struct {
- double *array; /**< a pointer of array */
- int count; /**< size of array */
- double d_val;
- } double_array;
- /**
- * Validity structure for double range.
- */
- struct {
- double min; /**< minimum range */
- double max; /**< maximum range */
- double d_val;
- } double_range;
- };
-} MMWfdAttrsInfo;
-
-MMHandleType _mmwfd_construct_attribute(MMHandleType hwfd);
-void _mmwfd_deconstruct_attribute(MMHandleType hwfd);
-int _mmwfd_set_attribute(MMHandleType hwfd, char **err_atr_name, const char *attribute_name, va_list args_list);
-int _mmwfd_get_attributes_info(MMHandleType handle, const char *attribute_name, MMWfdAttrsInfo *dst_info);
-int _mmwfd_get_attribute(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list args_list);
-#endif /* __MM_WFD_ATTRS_H__ */
\ No newline at end of file
+++ /dev/null
-/*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-#ifndef __MM_WFD_SINK_DLOG_H__
-#define __MM_WFD_SINK_DLOG_H__
-
-#include <dlog.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MM_WFD_SINK"
-
-#define FONT_COLOR_RESET "\033[0m"
-#define FONT_COLOR_RED "\033[31m"
-#define FONT_COLOR_GREEN "\033[32m"
-#define FONT_COLOR_YELLOW "\033[33m"
-#define FONT_COLOR_BLUE "\033[34m"
-#define FONT_COLOR_PURPLE "\033[35m"
-#define FONT_COLOR_CYAN "\033[36m"
-#define FONT_COLOR_GRAY "\033[37m"
-
-#define wfd_sink_debug(fmt, arg...) do { \
- LOGD(FONT_COLOR_RESET""fmt"", ##arg); \
- } while (0)
-
-#define wfd_sink_info(fmt, arg...) do { \
- LOGI(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
- } while (0)
-
-#define wfd_sink_error(fmt, arg...) do { \
- LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
- } while (0)
-
-#define wfd_sink_warning(fmt, arg...) do { \
- LOGW(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg); \
- } while (0)
-
-#define wfd_sink_debug_fenter() do { \
- LOGD(FONT_COLOR_RESET"<Enter>"); \
- } while (0)
-
-#define wfd_sink_debug_fleave() do { \
- LOGD(FONT_COLOR_RESET"<Leave>"); \
- } while (0)
-
-#define wfd_sink_error_fenter() do { \
- LOGE(FONT_COLOR_RED"NO-ERROR : <Enter>"FONT_COLOR_RESET); \
- } while (0)
-
-#define wfd_sink_error_fleave() do { \
- LOGE(FONT_COLOR_RED"NO-ERROR : <Leave>"FONT_COLOR_RESET); \
- } while (0)
-
-#define wfd_sink_sucure_info(fmt, arg...) do { \
- SECURE_LOGI(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
- } while (0)
-
-#define wfd_sink_return_if_fail(expr) \
- if(!(expr)) { \
- wfd_sink_error(FONT_COLOR_RED"failed [%s]\n"FONT_COLOR_RESET, #expr); \
- return; \
- }
-
-#define wfd_sink_return_val_if_fail(expr, val) \
- if (!(expr)) { \
- wfd_sink_error(FONT_COLOR_RED"failed [%s]\n"FONT_COLOR_RESET, #expr); \
- return val; \
- }
-
-#define wfd_sink_assert_not_reached() \
- { \
- wfd_sink_error(FONT_COLOR_RED"assert_not_reached()"FONT_COLOR_RESET); \
- assert(0); \
- }
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __MM_WFD_SINK_DLOG_H__ */
-
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef __MM_WFD_SINK_INI_H__
-#define __MM_WFD_SINK_INI_H__
-
-#include <glib.h>
-#include <tzplatform_config.h>
-#include "mm_wfd_sink_wfd_enum.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-enum WFDSinkINIProbeFlags
-{
- WFD_SINK_INI_PROBE_DEFAULT = 0,
- WFD_SINK_INI_PROBE_TIMESTAMP = (1 << 0),
- WFD_SINK_INI_PROBE_BUFFERSIZE = (1 << 1),
- WFD_SINK_INI_PROBE_CAPS = (1 << 2),
- WFD_SINK_INI_PROBE_BUFFER_DURATION = (1 << 3),
-};
-
-#define MM_WFD_SINK_INI_DEFAULT_PATH SYSCONFDIR"/multimedia/mmfw_wfd_sink.ini"
-
-#define WFD_SINK_INI_MAX_STRLEN 256
-#define WFD_SINK_INI_MAX_ELEMENT 10
-
-/* NOTE : MMPlayer has no initalizing API for library itself
- * so we cannot decide when those ini values to be released.
- * this is the reason of all string items are static array.
- * make it do with malloc when MMPlayerInitialize() API created
- * before that time, we should be careful with size limitation
- * of each string item.
- */
-typedef struct __mm_wfd_sink_ini {
- /* general */
- gchar gst_param[5][WFD_SINK_INI_MAX_STRLEN];
- gboolean generate_dot;
- gboolean enable_pad_probe;
- gint state_change_timeout;
- gboolean set_debug_property;
- gboolean enable_asm;
- gint jitter_buffer_latency;
- gint video_sink_max_lateness;
- gint sink_ts_offset;
- gboolean audio_sink_async;
- gboolean video_sink_async;
- gboolean enable_retransmission;
- gboolean enable_reset_basetime;
- gboolean enable_ts_data_dump;
- gboolean enable_wfdsrc_pad_probe;
-
- /* pipeline */
- gchar name_of_source[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_tsdemux[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_audio_hdcp[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_aac_parser[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_aac_decoder[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_ac3_parser[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_ac3_decoder[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_lpcm_converter[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_lpcm_filter[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_audio_resampler[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_audio_volume[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_audio_sink[WFD_SINK_INI_MAX_STRLEN];
-
- gchar name_of_video_hdcp[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_video_parser[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_video_capssetter[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_video_decoder[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_video_converter[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_video_filter[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_video_sink[WFD_SINK_INI_MAX_STRLEN];
- gchar name_of_video_evas_sink[WFD_SINK_INI_MAX_STRLEN];
-
- /* audio parameter for reponse of M3 request */
- guint audio_codec;
- guint audio_latency;
- guint audio_channel;
- guint audio_sampling_frequency;
-
- /* video parameter for reponse of M3 request */
- guint video_codec;
- guint video_native_resolution;
- guint video_cea_support;
- guint video_vesa_support;
- guint video_hh_support;
- guint video_profile;
- guint video_level;
- guint video_latency;
- gint video_vertical_resolution;
- gint video_horizontal_resolution;
- gint video_minimum_slicing;
- gint video_slice_enc_param;
- gint video_framerate_control_support;
-
- /* hdcp parameter for reponse of M3 request */
- gint hdcp_content_protection;
- gint hdcp_port_no;
-} mm_wfd_sink_ini_t;
-
-
-/*Default sink ini values*/
-/* General*/
-#define DEFAULT_GST_PARAM ""
-#define DEFAULT_GENERATE_DOT FALSE
-#define DEFAULT_ENABLE_PAD_PROBE FALSE
-#define DEFAULT_STATE_CHANGE_TIMEOUT 5 /* sec */
-#define DEFAULT_SET_DEBUG_PROPERTY TRUE
-#define DEFAULT_ENABLE_ASM FALSE
-#define DEFAULT_JITTER_BUFFER_LATENCY 10 /* msec */
-#define DEFAULT_ENABLE_RETRANSMISSION FALSE
-#define DEFAULT_ENABLE_RESET_BASETIME TRUE
-#define DEFAULT_VIDEO_SINK_MAX_LATENESS 20000000 /* nsec */
-#define DEFAULT_SINK_TS_OFFSET 150000000 /* nsec */
-#define DEFAULT_AUDIO_SINK_ASYNC FALSE
-#define DEFAULT_VIDEO_SINK_ASYNC FALSE
-#define DEFAULT_ENABLE_TS_DATA_DUMP FALSE
-#define DEFAULT_ENABLE_WFDRTSPSRC_PAD_PROBE FALSE
-
-/* Pipeline */
-#define DEFAULT_NAME_OF_SOURCE "wfdsrc"
-#define DEFAULT_NAME_OF_TSDEMUX ""
-#define DEFAULT_NAME_OF_AUDIO_HDCP ""
-#define DEFAULT_NAME_OF_AAC_PARSER ""
-#define DEFAULT_NAME_OF_AAC_DECODER ""
-#define DEFAULT_NAME_OF_AC3_PARSER ""
-#define DEFAULT_NAME_OF_AC3_DECODER ""
-#define DEFAULT_NAME_OF_LPCM_CONVERTER ""
-#define DEFAULT_NAME_OF_LPCM_FILTER ""
-#define DEFAULT_NAME_OF_AUDIO_RESAMPLER ""
-#define DEFAULT_NAME_OF_AUDIO_VOLUME ""
-#define DEFAULT_NAME_OF_AUDIO_SPLITTER ""
-#define DEFAULT_NAME_OF_AUDIO_SINK ""
-#define DEFAULT_NAME_OF_VIDEO_HDCP ""
-#define DEFAULT_NAME_OF_VIDEO_PARSER ""
-#define DEFAULT_NAME_OF_VIDEO_CAPSSETTER ""
-#define DEFAULT_NAME_OF_VIDEO_DECODER ""
-#define DEFAULT_NAME_OF_VIDEO_CONVERTER ""
-#define DEFAULT_NAME_OF_VIDEO_FILTER ""
-#define DEFAULT_NAME_OF_VIDEO_SINK ""
-#define DEFAULT_NAME_OF_EVAS_VIDEO_SINK ""
-
-/* Audio */
-#define DEFAULT_AUDIO_CODEC WFD_AUDIO_LPCM | WFD_AUDIO_AAC
-#define DEFAULT_AUDIO_LATENCY 0x0
-#define DEFAULT_AUDIO_CHANNELS WFD_CHANNEL_2
-#define DEFAULT_AUDIO_SAMP_FREQUENCY WFD_FREQ_44100 | WFD_FREQ_48000
-
-/* Video */
-#define DEFAULT_VIDEO_CODEC WFD_VIDEO_H264
-#define DEFAULT_VIDEO_NATIVE_RESOLUTION 0x20
-/* CEA : WFD_CEA_640x480P60 | WFD_CEA_720x480P60 |WFD_CEA_720x576P50 |WFD_CEA_1280x720P30 |
- WFD_CEA_1280x720P25 | WFD_CEA_1280x720P24 */
-#define DEFAULT_VIDEO_CEA_SUPPORT 0x84ab
-/* VESA : WFD_VESA_800x600P30 */
-#define DEFAULT_VIDEO_VESA_SUPPORT 0x1
-/* HH : WFD_HH_800x480P30 | WFD_HH_854x480P30 | WFD_HH_864x480P30 | WFD_HH_640x360P30 | WFD_HH_960x540P30 | WFD_HH_848x480P30 */
-#define DEFAULT_VIDEO_HH_SUPPORT 0x555
-#define DEFAULT_VIDEO_PROFILE WFD_H264_BASE_PROFILE
-#define DEFAULT_VIDEO_LEVEL WFD_H264_LEVEL_3_2
-#define DEFAULT_VIDEO_LATENCY 0x0
-#define DEFAULT_VIDEO_VERTICAL_RESOLUTION 720
-#define DEFAULT_VIDEO_HORIZONTAL_RESOLUTION 1280
-#define DEFAULT_VIDEO_MIN_SLICESIZE 0
-#define DEFAULT_VIDEO_SLICE_ENC_PARAM 200
-#define DEFAULT_VIDEO_FRAMERATE_CONTROL 11
-
-/* HDCP */
-#define DEFAULT_HDCP_CONTENT_PROTECTION 0x0
-#define DEFAULT_HDCP_PORT_NO 0
-
-
-#define MM_WFD_SINK_DEFAULT_INI \
-" \
-[general]\n\
-; parameters for initializing gstreamer\n\
-; DEFAULT SET(--gst-debug=2, *wfd*:5)\n\
-gstparam1 = --gst-debug=2, *wfd*:5, *wfdtsdemux:1, *wfdrtpbuffer:1\n\
-gstparam2 =\n\
-gstparam3 =\n\
-gstparam4 =\n\
-gstparam5 =\n\
-\n\
-; generating dot file representing pipeline state\n\
-; do export GST_DEBUG_DUMP_DOT_DIR=[dot file path] in the shell\n\
-generate dot = no\n\
-\n\
-; enable pad probe\n\
-enable pad probe = no\n\
-\n\
-; enable wfdsrc inner pad probe\n\
-enable wfdsrc pad probe = no\n\
-\n\
-; enable ts data dump(eg. /var/tmp/*.ts)\n\
-enable ts data dump = no\n\
-\n\
-; allowed timeout for changing pipeline state\n\
-state change timeout = 5 ; sec\n\
-\n\
-; set debug property to wfdsrc plugin for debugging rtsp message\n\
-set debug property = yes\n\
-\n\
-; for asm function enable = yes, disable = no\n\
-enable asm = no\n\
-\n\
-; 0: default value set by wfdsrc element, other: user define value.\n\
-jitter buffer latency=10\n\
-\n\
-; for retransmission request enable = yes, disable = no\n\
-enable retransmission = no\n\
-\n\
-; for reset basetime, enable = yes, disable = no\n\
-enable reset basetime = yes\n\
-\n\
-; Maximum number of nanoseconds that a buffer can be late before it is dropped by videosink(-1 unlimited)\n\
-video sink max lateness=20000000\n\
-\n\
-; nanoseconds to be added to buffertimestamp by sink elements\n\
-sink ts offset=150000000\n\
-\n\
-; if no, go asynchronously to PAUSED without preroll \n\
-audio sink async=no\n\
-\n\
-; if no, go asynchronously to PAUSED without preroll \n\
-video sink async=no\n\
-\n\
-\n\
-\n\
-[pipeline]\n\
-wfdsrc element = wfdsrc\n\
-\n\
-tsdemux element = wfdtsdemux\n\
-\n\
-aac parser element = aacparse\n\
-\n\
-aac decoder element = avdec_aac\n\
-\n\
-ac3 parser element = ac3parse\n\
-\n\
-ac3 decoder element =\n\
-\n\
-lpcm converter element =\n\
-\n\
-lpcm filter element = capsfilter\n\
-\n\
-audio resampler element = audioconvert\n\
-\n\
-audio volume element =\n\
-\n\
-audio sink element = pulsesink\n\
-\n\
-video parser element = h264parse\n\
-\n\
-video capssetter element = capssetter\n\
-\n\
-video decoder element = avdec_h264;sprddec_h264;omxh264dec\n\
-\n\
-video converter element =\n\
-\n\
-video filter element =\n\
-\n\
-video sink element = waylandsink;xvimagesink\n\
-\n\
-\n\
-\n\
-[audio param]\n\
-; 0x1: LPCM, 0x2: aac, 0x4: ac3\n\
-;default aac and LPCM\n\
-audio codec=0x3\n\
-\n\
-audio latency=0x0\n\
-\n\
-;0x1 : 48000khz, 0x2: 44100khz\n\
-audio sampling frequency=0x3\n\
-\n\
-; 0x1:2 channels, 0x2:4 channels, 0x4:6channels, 0x8:8channels\n\
-audio channels=0x1\n\
-\n\
-\n\
-\n\
-[video param]\n\
-; 0: H264CBP 1: H264CHP\n\
-video codec=0x1\n\
-\n\
-video native resolution = 0x20\n\
-\n\
-video cea support=0x842b\n\
-\n\
-video vesa support=0x1\n\
-\n\
-video hh support=0x555\n\
-\n\
-; 0x1:base, 0x2:high\n\
-video profile=0x1\n\
-\n\
-; 0x1:level_3_1, 0x2:level_3_2, 0x4:level_4, 0x8:level_4_1, 0x10:level_4_2\n\
-video level=0x2\n\
-\n\
-video latency=0x0\n\
-\n\
-video vertical resolution=720\n\
-\n\
-video horizontal resolution=1280\n\
-\n\
-video minimum slicesize=0\n\
-\n\
-video slice encoding params=200\n\
-\n\
-video framerate control support=11\n\
-\n\
-\n\
-\n\
-[hdcp param]\n\
-;0x0:none, 0x1:HDCP_2.0, 0x2:HDCP_2.1\n\
-hdcp content protection=0x0\n\
-\n\
-hdcp port no=0\n\
-\n\
-"
-
-int
-mm_wfd_sink_ini_load(mm_wfd_sink_ini_t *ini);
-
-int
-mm_wfd_sink_ini_unload(mm_wfd_sink_ini_t *ini);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/*
- * Enumeration for WFD
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef _MM_WFD_SINK_WFD_ENUM_H_
-#define _MM_WFD_SINK_WFD_ENUM_H_
-
-typedef enum {
- WFD_AUDIO_UNKNOWN = 0,
- WFD_AUDIO_LPCM = (1 << 0),
- WFD_AUDIO_AAC = (1 << 1),
- WFD_AUDIO_AC3 = (1 << 2)
-} WFDAudioFormats;
-
-typedef enum {
- WFD_FREQ_UNKNOWN = 0,
- WFD_FREQ_44100 = (1 << 0),
- WFD_FREQ_48000 = (1 << 1)
-} WFDAudioFreq;
-
-typedef enum {
- WFD_CHANNEL_UNKNOWN = 0,
- WFD_CHANNEL_2 = (1 << 0),
- WFD_CHANNEL_4 = (1 << 1),
- WFD_CHANNEL_6 = (1 << 2),
- WFD_CHANNEL_8 = (1 << 3)
-} WFDAudioChannels;
-
-
-typedef enum {
- WFD_VIDEO_UNKNOWN = 0,
- WFD_VIDEO_H264 = (1 << 0)
-} WFDVideoCodecs;
-
-typedef enum {
- WFD_VIDEO_CEA_RESOLUTION = 0,
- WFD_VIDEO_VESA_RESOLUTION,
- WFD_VIDEO_HH_RESOLUTION
-} WFDVideoNativeResolution;
-
-typedef enum {
- WFD_CEA_UNKNOWN = 0,
- WFD_CEA_640x480P60 = (1 << 0),
- WFD_CEA_720x480P60 = (1 << 1),
- WFD_CEA_720x480I60 = (1 << 2),
- WFD_CEA_720x576P50 = (1 << 3),
- WFD_CEA_720x576I50 = (1 << 4),
- WFD_CEA_1280x720P30 = (1 << 5),
- WFD_CEA_1280x720P60 = (1 << 6),
- WFD_CEA_1920x1080P30 = (1 << 7),
- WFD_CEA_1920x1080P60 = (1 << 8),
- WFD_CEA_1920x1080I60 = (1 << 9),
- WFD_CEA_1280x720P25 = (1 << 10),
- WFD_CEA_1280x720P50 = (1 << 11),
- WFD_CEA_1920x1080P25 = (1 << 12),
- WFD_CEA_1920x1080P50 = (1 << 13),
- WFD_CEA_1920x1080I50 = (1 << 14),
- WFD_CEA_1280x720P24 = (1 << 15),
- WFD_CEA_1920x1080P24 = (1 << 16)
-} WFDVideoCEAResolution;
-
-typedef enum {
- WFD_VESA_UNKNOWN = 0,
- WFD_VESA_800x600P30 = (1 << 0),
- WFD_VESA_800x600P60 = (1 << 1),
- WFD_VESA_1024x768P30 = (1 << 2),
- WFD_VESA_1024x768P60 = (1 << 3),
- WFD_VESA_1152x864P30 = (1 << 4),
- WFD_VESA_1152x864P60 = (1 << 5),
- WFD_VESA_1280x768P30 = (1 << 6),
- WFD_VESA_1280x768P60 = (1 << 7),
- WFD_VESA_1280x800P30 = (1 << 8),
- WFD_VESA_1280x800P60 = (1 << 9),
- WFD_VESA_1360x768P30 = (1 << 10),
- WFD_VESA_1360x768P60 = (1 << 11),
- WFD_VESA_1366x768P30 = (1 << 12),
- WFD_VESA_1366x768P60 = (1 << 13),
- WFD_VESA_1280x1024P30 = (1 << 14),
- WFD_VESA_1280x1024P60 = (1 << 15),
- WFD_VESA_1400x1050P30 = (1 << 16),
- WFD_VESA_1400x1050P60 = (1 << 17),
- WFD_VESA_1440x900P30 = (1 << 18),
- WFD_VESA_1440x900P60 = (1 << 19),
- WFD_VESA_1600x900P30 = (1 << 20),
- WFD_VESA_1600x900P60 = (1 << 21),
- WFD_VESA_1600x1200P30 = (1 << 22),
- WFD_VESA_1600x1200P60 = (1 << 23),
- WFD_VESA_1680x1024P30 = (1 << 24),
- WFD_VESA_1680x1024P60 = (1 << 25),
- WFD_VESA_1680x1050P30 = (1 << 26),
- WFD_VESA_1680x1050P60 = (1 << 27),
- WFD_VESA_1920x1200P30 = (1 << 28),
- WFD_VESA_1920x1200P60 = (1 << 29)
-} WFDVideoVESAResolution;
-
-typedef enum {
- WFD_HH_UNKNOWN = 0,
- WFD_HH_800x480P30 = (1 << 0),
- WFD_HH_800x480P60 = (1 << 1),
- WFD_HH_854x480P30 = (1 << 2),
- WFD_HH_854x480P60 = (1 << 3),
- WFD_HH_864x480P30 = (1 << 4),
- WFD_HH_864x480P60 = (1 << 5),
- WFD_HH_640x360P30 = (1 << 6),
- WFD_HH_640x360P60 = (1 << 7),
- WFD_HH_960x540P30 = (1 << 8),
- WFD_HH_960x540P60 = (1 << 9),
- WFD_HH_848x480P30 = (1 << 10),
- WFD_HH_848x480P60 = (1 << 11)
-} WFDVideoHHResolution;
-
-typedef enum {
- WFD_H264_UNKNOWN_PROFILE = 0,
- WFD_H264_BASE_PROFILE = (1 << 0),
- WFD_H264_HIGH_PROFILE = (1 << 1)
-} WFDVideoH264Profile;
-
-typedef enum {
- WFD_H264_LEVEL_UNKNOWN = 0,
- WFD_H264_LEVEL_3_1 = (1 << 0),
- WFD_H264_LEVEL_3_2 = (1 << 1),
- WFD_H264_LEVEL_4 = (1 << 2),
- WFD_H264_LEVEL_4_1 = (1 << 3),
- WFD_H264_LEVEL_4_2 = (1 << 4)
-} WFDVideoH264Level;
-
-#endif /*_MM_WFD_SINK_WFD_ENUM_H_*/
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "mm_wfd_attrs.h"
-
-typedef struct {
- char *name;
- int value_type;
- int flags; /* r, w */
- void *default_value;
- int valid_type;
- int value_min;
- int value_max;
-} MMWfdAttrsSpec;
-
-/*static gboolean __mmwfd_apply_attribute(MMHandleType handle, const char *attribute_name); */
-
-MMHandleType
-_mmwfd_construct_attribute(MMHandleType handle)
-{
- int idx = 0;
- MMHandleType attrs = 0;
- int num_of_attrs = 0;
- mmf_attrs_construct_info_t *base = NULL;
-
- debug_fenter();
-
- return_val_if_fail(handle, (MMHandleType) NULL);
-
- MMWfdAttrsSpec wfd_attrs[] = {
- {
- (char *)"server_ip",
- MM_ATTRS_TYPE_STRING,
- MM_ATTRS_FLAG_RW,
- (void *)"127.0.0.1",
- MM_ATTRS_VALID_TYPE_NONE,
- 0,
- 0
- },
-
- {
- (char *)"server_port",
- MM_ATTRS_TYPE_STRING,
- MM_ATTRS_FLAG_RW,
- (void *)"8554",
- MM_ATTRS_VALID_TYPE_NONE,
- 0,
- 0
- },
-
- {
- (char *)"max_client_count",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *)1,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 10
- },
- /* Initialized with invalid native type, if a valid value is set then only this atribute will be considered */
- {
- (char *)"native_resolution",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *)0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 3
- },
- /* Initialized with invalid resolution, if a valid value is set then only this atribute will be considered */
- {
- (char *)"prefered_resolutions",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *)2147483647,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 2147483647
- },
- /* Initialized with invalid uibc option, if a valid value is set then only this atribute will be considered */
- {
- (char *)"set_hdcp",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *)2,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 2
- },
- {
- (char *)"display_rotate",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *)0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 3
- },
- {
- (char *)"display_src_crop_x",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_src_crop_y",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_src_crop_width",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_src_crop_height",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_roi_x",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_roi_y",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_roi_width",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 480,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_roi_height",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 800,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_roi_mode",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) MM_DISPLAY_METHOD_CUSTOM_ROI_FULL_SCREEN,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- MM_DISPLAY_METHOD_CUSTOM_ROI_FULL_SCREEN,
- MM_DISPLAY_METHOD_CUSTOM_ROI_LETER_BOX
- },
- {
- (char *)"display_rotation",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) MM_DISPLAY_ROTATION_NONE,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- MM_DISPLAY_ROTATION_NONE,
- MM_DISPLAY_ROTATION_270
- },
- {
- (char *)"display_visible",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) TRUE,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 1
- },
- {
- (char *)"display_method",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) MM_DISPLAY_METHOD_LETTER_BOX,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- MM_DISPLAY_METHOD_LETTER_BOX,
- MM_DISPLAY_METHOD_CUSTOM_ROI
- },
- {
- (char *)"display_overlay",
- MM_ATTRS_TYPE_DATA,
- MM_ATTRS_FLAG_RW,
- (void *) NULL,
- MM_ATTRS_VALID_TYPE_NONE,
- 0,
- 0
- },
- {
- (char *)"display_overlay_user_data",
- MM_ATTRS_TYPE_DATA,
- MM_ATTRS_FLAG_RW,
- (void *) NULL,
- MM_ATTRS_VALID_TYPE_NONE,
- 0,
- 0
- },
- {
- (char *)"display_zoom",
- MM_ATTRS_TYPE_DOUBLE,
- MM_ATTRS_FLAG_RW,
- (void *) 1,
- MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
- 1.0,
- 9.0
- },
- {
- (char *)"display_surface_type",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) MM_DISPLAY_SURFACE_OVERLAY,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- MM_DISPLAY_SURFACE_OVERLAY,
- MM_DISPLAY_SURFACE_REMOTE
- },
- {
- (char *)"display_width", /* dest width of fimcconvert ouput */
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_height", /* dest height of fimcconvert ouput */
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_evas_do_scaling",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) TRUE,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- FALSE,
- TRUE
- },
- {
- (char *)"display_x",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"display_y",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 4096
- },
- {
- (char *)"hdcp_version",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 2
- },
- {
- (char *)"hdcp_port",
- MM_ATTRS_TYPE_INT,
- MM_ATTRS_FLAG_RW,
- (void *) 0,
- MM_ATTRS_VALID_TYPE_INT_RANGE,
- 0,
- 2147483647
- },
- };
-
- num_of_attrs = ARRAY_SIZE(wfd_attrs);
-
- base = (mmf_attrs_construct_info_t *)malloc(num_of_attrs * sizeof(mmf_attrs_construct_info_t));
-
- if (!base) {
- debug_error("Cannot create mmwfd attribute\n");
- goto ERROR;
- }
-
- /* initialize values of attributes */
- for (idx = 0; idx < num_of_attrs; idx++) {
- base[idx].name = wfd_attrs[idx].name;
- base[idx].value_type = wfd_attrs[idx].value_type;
- base[idx].flags = wfd_attrs[idx].flags;
- base[idx].default_value = wfd_attrs[idx].default_value;
- }
-
- attrs = mmf_attrs_new_from_data(
- "mmwfd_attrs",
- base,
- num_of_attrs,
- NULL,
- NULL);
-
- if (base) {
- g_free(base);
- base = NULL;
- }
-
- if (!attrs) {
- debug_error("Cannot create mmwfd attribute\n");
- goto ERROR;
- }
-
- /* set validity type and range */
- for (idx = 0; idx < num_of_attrs; idx++) {
- switch (wfd_attrs[idx].valid_type) {
- case MM_ATTRS_VALID_TYPE_INT_RANGE: {
- mmf_attrs_set_valid_type(attrs, idx, MM_ATTRS_VALID_TYPE_INT_RANGE);
- mmf_attrs_set_valid_range(attrs, idx,
- wfd_attrs[idx].value_min,
- wfd_attrs[idx].value_max,
- (int)wfd_attrs[idx].default_value);
- }
- break;
-
- case MM_ATTRS_VALID_TYPE_INT_ARRAY:
- case MM_ATTRS_VALID_TYPE_DOUBLE_ARRAY:
- case MM_ATTRS_VALID_TYPE_DOUBLE_RANGE:
- default:
- break;
- }
- }
-
- debug_fleave();
-
- return attrs;
-
-ERROR:
- _mmwfd_deconstruct_attribute(attrs);
-
- return (MMHandleType)NULL;
-}
-
-void
-_mmwfd_deconstruct_attribute(MMHandleType handle)
-{
- debug_fenter();
-
- return_if_fail(handle);
-
- if (handle)
- mmf_attrs_free(handle);
-
- debug_fleave();
-}
-
-int
-_mmwfd_get_attribute(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list args_list)
-{
- int result = MM_ERROR_NONE;
- MMHandleType attrs = 0;
-
- debug_fenter();
-
- /* NOTE : Don't need to check err_attr_name because it can be set NULL */
- /* if it's not want to know it. */
- return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
- return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- attrs = handle;
-
- return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- result = mm_attrs_get_valist(attrs, err_attr_name, attribute_name, args_list);
-
- if (result != MM_ERROR_NONE)
- debug_error("failed to get %s attribute\n", attribute_name);
-
- debug_fleave();
-
- return result;
-}
-
-int
-_mmwfd_set_attribute(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list args_list)
-{
- int result = MM_ERROR_NONE;
- MMHandleType attrs = 0;
-
- debug_fenter();
-
- /* NOTE : Don't need to check err_attr_name because it can be set NULL */
- /* if it's not want to know it. */
- return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
- return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- attrs = handle;
-
- return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- /* set attributes and commit them */
- result = mm_attrs_set_valist(attrs, err_attr_name, attribute_name, args_list);
-
- if (result != MM_ERROR_NONE) {
- debug_error("failed to set %s attribute\n", attribute_name);
- return result;
- }
-
- /*__mmwfd_apply_attribute(handle, attribute_name); */
-
- debug_fleave();
-
- return result;
-}
-
-/* Currently not used. */
-/*static gboolean
-__mmwfd_apply_attribute(MMHandleType handle, const char *attribute_name)
-{
- MMHandleType attrs = 0;
- mm_wfd_t* wfd = 0;
-
- debug_fenter();
-
- return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
- return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- attrs = handle;
-
- return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- wfd = (mm_wfd_t*)handle;
-
- // TODO: This function is not useful at this moment
-
- debug_fleave();
-
- return TRUE;
-}*/
-
-int
-_mmwfd_get_attributes_info(MMHandleType handle, const char *attribute_name, MMWfdAttrsInfo *dst_info)
-{
- int result = MM_ERROR_NONE;
- MMHandleType attrs = 0;
- MMAttrsInfo src_info = {0, };
-
- debug_fenter();
-
- return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
- return_val_if_fail(dst_info, MM_ERROR_COMMON_INVALID_ARGUMENT);
- return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- attrs = handle;
-
- return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- result = mm_attrs_get_info_by_name(attrs, attribute_name, &src_info);
-
- if (result != MM_ERROR_NONE) {
- debug_error("failed to get attribute info\n");
- return result;
- }
-
- memset(dst_info, 0x00, sizeof(MMWfdAttrsInfo));
-
- dst_info->type = src_info.type;
- dst_info->flag = src_info.flag;
- dst_info->validity_type = src_info.validity_type;
-
- switch (src_info.validity_type) {
- case MM_ATTRS_VALID_TYPE_INT_ARRAY:
- dst_info->int_array.array = src_info.int_array.array;
- dst_info->int_array.count = src_info.int_array.count;
- dst_info->int_array.d_val = src_info.int_array.dval;
- break;
-
- case MM_ATTRS_VALID_TYPE_INT_RANGE:
- dst_info->int_range.min = src_info.int_range.min;
- dst_info->int_range.max = src_info.int_range.max;
- dst_info->int_range.d_val = src_info.int_range.dval;
- break;
-
- case MM_ATTRS_VALID_TYPE_DOUBLE_ARRAY:
- dst_info->double_array.array = src_info.double_array.array;
- dst_info->double_array.count = src_info.double_array.count;
- dst_info->double_array.d_val = src_info.double_array.dval;
- break;
-
- case MM_ATTRS_VALID_TYPE_DOUBLE_RANGE:
- dst_info->double_range.min = src_info.double_range.min;
- dst_info->double_range.max = src_info.double_range.max;
- dst_info->double_range.d_val = src_info.double_range.dval;
- break;
-
- default:
- break;
- }
-
- debug_fleave();
-
- return result;
-}
-
-
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <stdlib.h>
-#include <iniparser.h>
-#include <mm_error.h>
-#include "mm_wfd_sink_ini.h"
-#include "mm_wfd_sink_dlog.h"
-
-static gboolean loaded = FALSE;
-
-/* global variables here */
-#ifdef MM_WFD_SINK_DEFAULT_INI
-static gboolean __generate_sink_default_ini(void);
-#endif
-
-static void __mm_wfd_sink_ini_check_status(void);
-
-/* macro */
-#define MM_WFD_SINK_INI_GET_STRING(x_dict, x_item, x_ini, x_default) \
- do { \
- gchar *str = NULL; \
- gint length = 0; \
- \
- str = iniparser_getstring(x_dict, x_ini, (char *)x_default); \
- if (str) { \
- length = strlen(str); \
- if ((length > 1) && (length < WFD_SINK_INI_MAX_STRLEN)) \
- strncpy(x_item, str, WFD_SINK_INI_MAX_STRLEN-1); \
- else \
- strncpy(x_item, x_default, WFD_SINK_INI_MAX_STRLEN-1); \
- } else { \
- strncpy(x_item, x_default, WFD_SINK_INI_MAX_STRLEN-1); \
- } \
- } while (0);
-
-#ifdef MM_WFD_SINK_DEFAULT_INI
-static
-gboolean __generate_sink_default_ini(void)
-{
- FILE *fp = NULL;
- const gchar *default_ini = MM_WFD_SINK_DEFAULT_INI;
-
-
- /* create new file */
- fp = fopen(MM_WFD_SINK_INI_DEFAULT_PATH, "wt");
-
- if (!fp) {
- return FALSE;
- }
-
- /* writing default ini file */
- if (strlen(default_ini) != fwrite(default_ini, 1, strlen(default_ini), fp)) {
- fclose(fp);
- return FALSE;
- }
-
- fclose(fp);
- return TRUE;
-}
-#endif
-
-int
-mm_wfd_sink_ini_load(mm_wfd_sink_ini_t *ini)
-{
- dictionary *dict = NULL;
-
- wfd_sink_debug_fenter();
-
-
- __mm_wfd_sink_ini_check_status();
-
- /* first, try to load existing ini file */
- dict = iniparser_load(MM_WFD_SINK_INI_DEFAULT_PATH);
-
- /* if no file exists. create one with set of default values */
- if (!dict) {
-#ifdef MM_WFD_SINK_DEFAULT_INI
- wfd_sink_debug("No inifile found. create default ini file.\n");
- if (FALSE == __generate_sink_default_ini()) {
- wfd_sink_error("Creating default ini file failed. Use default values.\n");
- } else {
- /* load default ini */
- dict = iniparser_load(MM_WFD_SINK_INI_DEFAULT_PATH);
- }
-#else
- wfd_sink_error("No ini file found. \n");
-
- return MM_ERROR_FILE_NOT_FOUND;
-#endif
- }
-
- /* get ini values */
- memset(ini, 0, sizeof(mm_wfd_sink_ini_t));
-
- if (dict) { /* if dict is available */
- /* general */
- MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[0], "general:gstparam1", DEFAULT_GST_PARAM);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[1], "general:gstparam2", DEFAULT_GST_PARAM);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[2], "general:gstparam3", DEFAULT_GST_PARAM);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[3], "general:gstparam4", DEFAULT_GST_PARAM);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[4], "general:gstparam5", DEFAULT_GST_PARAM);
- ini->generate_dot = iniparser_getboolean(dict, "general:generate dot", DEFAULT_GENERATE_DOT);
- ini->enable_pad_probe = iniparser_getboolean(dict, "general:enable pad probe", DEFAULT_ENABLE_PAD_PROBE);
- ini->state_change_timeout = iniparser_getint(dict, "general:state change timeout", DEFAULT_STATE_CHANGE_TIMEOUT);
- ini->set_debug_property = iniparser_getboolean(dict, "general:set debug property", DEFAULT_SET_DEBUG_PROPERTY);
- ini->enable_asm = iniparser_getboolean(dict, "general:enable asm", DEFAULT_ENABLE_ASM);
- ini->jitter_buffer_latency = iniparser_getint(dict, "general:jitter buffer latency", DEFAULT_JITTER_BUFFER_LATENCY);
- ini->enable_retransmission = iniparser_getboolean(dict, "general:enable retransmission", DEFAULT_ENABLE_RETRANSMISSION);
- ini->enable_reset_basetime = iniparser_getboolean(dict, "general:enable reset basetime", DEFAULT_ENABLE_RESET_BASETIME);
- ini->video_sink_max_lateness = iniparser_getint(dict, "general:video sink max lateness", DEFAULT_VIDEO_SINK_MAX_LATENESS);
- ini->sink_ts_offset = iniparser_getint(dict, "general:sink ts offset", DEFAULT_SINK_TS_OFFSET);
- ini->audio_sink_async = iniparser_getboolean(dict, "general:audio sink async", DEFAULT_AUDIO_SINK_ASYNC);
- ini->video_sink_async = iniparser_getboolean(dict, "general:video sink async", DEFAULT_VIDEO_SINK_ASYNC);
- ini->enable_ts_data_dump = iniparser_getboolean(dict, "general:enable ts data dump", DEFAULT_ENABLE_TS_DATA_DUMP);
- ini->enable_wfdsrc_pad_probe = iniparser_getboolean(dict, "general:enable wfdsrc pad probe", DEFAULT_ENABLE_WFDRTSPSRC_PAD_PROBE);
-
-
- /* pipeline */
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_source, "pipeline:wfdsrc element", DEFAULT_NAME_OF_SOURCE);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_tsdemux, "pipeline:tsdemux element", DEFAULT_NAME_OF_TSDEMUX);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_audio_hdcp, "pipeline:audio hdcp element", DEFAULT_NAME_OF_AUDIO_HDCP);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_aac_parser, "pipeline:aac parser element", DEFAULT_NAME_OF_AAC_PARSER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_aac_decoder, "pipeline:aac decoder element", DEFAULT_NAME_OF_AAC_DECODER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_ac3_parser, "pipeline:ac3 parser element", DEFAULT_NAME_OF_AC3_PARSER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_ac3_decoder, "pipeline:ac3 decoder element", DEFAULT_NAME_OF_AC3_DECODER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_lpcm_converter, "pipeline:lpcm converter element", DEFAULT_NAME_OF_LPCM_CONVERTER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_lpcm_filter, "pipeline:lpcm filter element", DEFAULT_NAME_OF_LPCM_FILTER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_audio_resampler, "pipeline:audio resampler element", DEFAULT_NAME_OF_AUDIO_RESAMPLER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_audio_volume, "pipeline:audio volume element", DEFAULT_NAME_OF_AUDIO_VOLUME);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_audio_sink, "pipeline:audio sink element", DEFAULT_NAME_OF_AUDIO_SINK);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_hdcp, "pipeline:video hdcp element", DEFAULT_NAME_OF_VIDEO_HDCP);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_parser, "pipeline:video parser element", DEFAULT_NAME_OF_VIDEO_PARSER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_capssetter, "pipeline:video capssetter element", DEFAULT_NAME_OF_VIDEO_CAPSSETTER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_decoder, "pipeline:video decoder element", DEFAULT_NAME_OF_VIDEO_DECODER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_converter, "pipeline:video converter element", DEFAULT_NAME_OF_VIDEO_CONVERTER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_filter, "pipeline:video filter element", DEFAULT_NAME_OF_VIDEO_FILTER);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_sink, "pipeline:video sink element", DEFAULT_NAME_OF_VIDEO_SINK);
- MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_evas_sink, "pipeline:video evas sink element", DEFAULT_NAME_OF_EVAS_VIDEO_SINK);
-
- /* audio parameter*/
- ini->audio_codec = iniparser_getint(dict, "audio param:audio codec", DEFAULT_AUDIO_CODEC);
- ini->audio_latency = iniparser_getint(dict, "audio param:audio latency", DEFAULT_AUDIO_LATENCY);
- ini->audio_channel = iniparser_getint(dict, "audio param:audio channels", DEFAULT_AUDIO_CHANNELS);
- ini->audio_sampling_frequency = iniparser_getint(dict, "audio param:audio sampling frequency", DEFAULT_AUDIO_SAMP_FREQUENCY);
-
- /* video parameter*/
- ini->video_codec = iniparser_getint(dict, "video param:video codec", DEFAULT_VIDEO_CODEC);
- ini->video_native_resolution = iniparser_getint(dict, "video param:video native resolution", DEFAULT_VIDEO_NATIVE_RESOLUTION);
- ini->video_cea_support = iniparser_getint(dict, "video param:video cea support", DEFAULT_VIDEO_CEA_SUPPORT);
- ini->video_vesa_support = iniparser_getint(dict, "video param:video vesa support", DEFAULT_VIDEO_VESA_SUPPORT);
- ini->video_hh_support = iniparser_getint(dict, "video param:video hh support", DEFAULT_VIDEO_HH_SUPPORT);
- ini->video_profile = iniparser_getint(dict, "video param:video profile", DEFAULT_VIDEO_PROFILE);
- ini->video_level = iniparser_getint(dict, "video param:video level", DEFAULT_VIDEO_LEVEL);
- ini->video_latency = iniparser_getint(dict, "video param:video latency", DEFAULT_VIDEO_LATENCY);
- ini->video_vertical_resolution = iniparser_getint(dict, "video param:video vertical resolution", DEFAULT_VIDEO_VERTICAL_RESOLUTION);
- ini->video_horizontal_resolution = iniparser_getint(dict, "video param:video horizontal resolution", DEFAULT_VIDEO_HORIZONTAL_RESOLUTION);
- ini->video_minimum_slicing = iniparser_getint(dict, "video param:video minimum slicesize", DEFAULT_VIDEO_MIN_SLICESIZE);
- ini->video_slice_enc_param = iniparser_getint(dict, "video param:video slice encoding params", DEFAULT_VIDEO_SLICE_ENC_PARAM);
- ini->video_framerate_control_support = iniparser_getint(dict, "video param:video framerate control support", DEFAULT_VIDEO_FRAMERATE_CONTROL);
-
- /* hdcp parameter*/
- ini->hdcp_content_protection = iniparser_getint(dict, "hdcp param:hdcp content protection", DEFAULT_HDCP_CONTENT_PROTECTION);
- ini->hdcp_port_no = iniparser_getint(dict, "hdcp param:hdcp port no", DEFAULT_HDCP_PORT_NO);
- } else { /* if dict is not available just fill the structure with default value */
- wfd_sink_error("failed to load ini. using hardcoded default\n");
-
- /* general */
- strncpy(ini->gst_param[0], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->gst_param[1], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->gst_param[2], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->gst_param[3], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->gst_param[4], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
- ini->generate_dot = DEFAULT_GENERATE_DOT;
- ini->enable_pad_probe = DEFAULT_ENABLE_PAD_PROBE;
- ini->state_change_timeout = DEFAULT_STATE_CHANGE_TIMEOUT;
- ini->set_debug_property = DEFAULT_SET_DEBUG_PROPERTY;
- ini->enable_asm = DEFAULT_ENABLE_ASM;
- ini->jitter_buffer_latency = DEFAULT_JITTER_BUFFER_LATENCY;
- ini->enable_retransmission = DEFAULT_ENABLE_RETRANSMISSION;
- ini->enable_reset_basetime = DEFAULT_ENABLE_RESET_BASETIME;
- ini->video_sink_max_lateness = DEFAULT_VIDEO_SINK_MAX_LATENESS;
- ini->sink_ts_offset = DEFAULT_SINK_TS_OFFSET;
- ini->enable_ts_data_dump = DEFAULT_ENABLE_TS_DATA_DUMP;
- ini->enable_wfdsrc_pad_probe = DEFAULT_ENABLE_WFDRTSPSRC_PAD_PROBE;
-
- /* pipeline */
- strncpy(ini->name_of_source, DEFAULT_NAME_OF_TSDEMUX, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_tsdemux, DEFAULT_NAME_OF_TSDEMUX, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_audio_hdcp, DEFAULT_NAME_OF_AUDIO_HDCP, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_aac_parser, DEFAULT_NAME_OF_AAC_PARSER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_aac_decoder, DEFAULT_NAME_OF_AAC_DECODER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_ac3_parser, DEFAULT_NAME_OF_AC3_PARSER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_ac3_decoder, DEFAULT_NAME_OF_AC3_DECODER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_lpcm_converter, DEFAULT_NAME_OF_LPCM_CONVERTER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_lpcm_filter, DEFAULT_NAME_OF_LPCM_FILTER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_audio_resampler, DEFAULT_NAME_OF_AUDIO_RESAMPLER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_audio_volume, DEFAULT_NAME_OF_AUDIO_VOLUME, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_audio_sink, DEFAULT_NAME_OF_AUDIO_SINK, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_video_hdcp, DEFAULT_NAME_OF_VIDEO_HDCP, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_video_parser, DEFAULT_NAME_OF_VIDEO_PARSER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_video_capssetter, DEFAULT_NAME_OF_VIDEO_CAPSSETTER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_video_decoder, DEFAULT_NAME_OF_VIDEO_DECODER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_video_converter, DEFAULT_NAME_OF_VIDEO_CONVERTER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_video_filter, DEFAULT_NAME_OF_VIDEO_FILTER, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_video_sink, DEFAULT_NAME_OF_VIDEO_SINK, WFD_SINK_INI_MAX_STRLEN - 1);
- strncpy(ini->name_of_video_evas_sink, DEFAULT_NAME_OF_EVAS_VIDEO_SINK, WFD_SINK_INI_MAX_STRLEN - 1);
-
- /* audio parameter*/
- ini->audio_codec = DEFAULT_AUDIO_CODEC;
- ini->audio_latency = DEFAULT_AUDIO_LATENCY;
- ini->audio_channel = DEFAULT_AUDIO_CHANNELS;
- ini->audio_sampling_frequency = DEFAULT_AUDIO_SAMP_FREQUENCY;
-
- /* video parameter*/
- ini->video_codec = DEFAULT_VIDEO_CODEC;
- ini->video_native_resolution = DEFAULT_VIDEO_NATIVE_RESOLUTION;
- ini->video_cea_support = DEFAULT_VIDEO_CEA_SUPPORT;
- ini->video_vesa_support = DEFAULT_VIDEO_VESA_SUPPORT;
- ini->video_hh_support = DEFAULT_VIDEO_HH_SUPPORT;
- ini->video_profile = DEFAULT_VIDEO_PROFILE;
- ini->video_level = DEFAULT_VIDEO_LEVEL;
- ini->video_latency = DEFAULT_VIDEO_LATENCY;
- ini->video_vertical_resolution = DEFAULT_VIDEO_VERTICAL_RESOLUTION;
- ini->video_horizontal_resolution = DEFAULT_VIDEO_HORIZONTAL_RESOLUTION;
- ini->video_minimum_slicing = DEFAULT_VIDEO_MIN_SLICESIZE;
- ini->video_slice_enc_param = DEFAULT_VIDEO_SLICE_ENC_PARAM;
- ini->video_framerate_control_support = DEFAULT_VIDEO_FRAMERATE_CONTROL;
-
- /* hdcp parameter*/
- ini->hdcp_content_protection = DEFAULT_HDCP_CONTENT_PROTECTION;
- ini->hdcp_port_no = DEFAULT_HDCP_PORT_NO;
- }
-
- /* free dict as we got our own structure */
- iniparser_freedict(dict);
-
-
- /* dump structure */
- wfd_sink_debug("W-Fi Display Sink Initial Settings-----------------------------------\n");
-
- /* general */
- wfd_sink_debug("gst_param1 : %s\n", ini->gst_param[0]);
- wfd_sink_debug("gst_param2 : %s\n", ini->gst_param[1]);
- wfd_sink_debug("gst_param3 : %s\n", ini->gst_param[2]);
- wfd_sink_debug("gst_param4 : %s\n", ini->gst_param[3]);
- wfd_sink_debug("gst_param5 : %s\n", ini->gst_param[4]);
- wfd_sink_debug("generate_dot : %d\n", ini->generate_dot);
- if (ini->generate_dot == TRUE) {
- wfd_sink_debug("generate_dot is TRUE, dot file will be stored into /tmp/\n");
- g_setenv("GST_DEBUG_DUMP_DOT_DIR", "/tmp/", FALSE);
- }
- wfd_sink_debug("enable_pad_probe : %d\n", ini->enable_pad_probe);
- wfd_sink_debug("state_change_timeout(sec) : %d\n", ini->state_change_timeout);
- wfd_sink_debug("set_debug_property : %d\n", ini->set_debug_property);
- wfd_sink_debug("enable_asm : %d\n", ini->enable_asm);
- wfd_sink_debug("jitter_buffer_latency(msec) : %d\n", ini->jitter_buffer_latency);
- wfd_sink_debug("enable_retransmission : %d\n", ini->enable_retransmission);
- wfd_sink_debug("enable_reset_basetime : %d\n", ini->enable_reset_basetime);
- wfd_sink_debug("video_sink_max_lateness(nsec) : %d\n", ini->video_sink_max_lateness);
- wfd_sink_debug("sink_ts_offset(nsec) : %d\n", ini->sink_ts_offset);
- wfd_sink_debug("audio_sink_async : %d\n", ini->audio_sink_async);
- wfd_sink_debug("video_sink_async : %d\n", ini->video_sink_async);
- wfd_sink_debug("enable_ts_data_dump : %d\n", ini->enable_ts_data_dump);
- wfd_sink_debug("enable_wfdsrc_pad_probe : %d\n", ini->enable_wfdsrc_pad_probe);
-
- /* pipeline */
- wfd_sink_debug("name_of_source : %s\n", ini->name_of_source);
- wfd_sink_debug("name_of_tsdemux : %s\n", ini->name_of_tsdemux);
- wfd_sink_debug("name_of_audio_hdcp : %s\n", ini->name_of_audio_hdcp);
- wfd_sink_debug("name_of_aac_parser : %s\n", ini->name_of_aac_parser);
- wfd_sink_debug("name_of_aac_decoder : %s\n", ini->name_of_aac_decoder);
- wfd_sink_debug("name_of_ac3_parser : %s\n", ini->name_of_ac3_parser);
- wfd_sink_debug("name_of_ac3_decoder : %s\n", ini->name_of_ac3_decoder);
- wfd_sink_debug("name_of_lpcm_converter : %s\n", ini->name_of_lpcm_converter);
- wfd_sink_debug("name_of_lpcm_filter : %s\n", ini->name_of_lpcm_filter);
- wfd_sink_debug("name_of_audio_resampler : %s\n", ini->name_of_audio_resampler);
- wfd_sink_debug("name_of_audio_volume : %s\n", ini->name_of_audio_volume);
- wfd_sink_debug("name_of_audio_sink : %s\n", ini->name_of_audio_sink);
- wfd_sink_debug("name_of_video_hdcp : %s\n", ini->name_of_video_hdcp);
- wfd_sink_debug("name_of_video_parser : %s\n", ini->name_of_video_parser);
- wfd_sink_debug("name_of_video_capssetter : %s\n", ini->name_of_video_capssetter);
- wfd_sink_debug("name_of_video_decoder : %s\n", ini->name_of_video_decoder);
- wfd_sink_debug("name_of_video_converter : %s\n", ini->name_of_video_converter);
- wfd_sink_debug("name_of_video_filter : %s\n", ini->name_of_video_filter);
- wfd_sink_debug("name_of_video_sink : %s\n", ini->name_of_video_sink);
- wfd_sink_debug("name_of_video_evas_sink : %s\n", ini->name_of_video_evas_sink);
-
- /* audio parameter*/
- wfd_sink_debug("audio_codec : %x\n", ini->audio_codec);
- wfd_sink_debug("audio_latency : %d\n", ini->audio_latency);
- wfd_sink_debug("audio_channel : %x\n", ini->audio_channel);
- wfd_sink_debug("audio_sampling_frequency : %x\n", ini->audio_sampling_frequency);
-
- /* video parameter*/
- wfd_sink_debug("video_codec : %x\n", ini->video_codec);
- wfd_sink_debug("video_native_resolution : %x\n", ini->video_native_resolution);
- wfd_sink_debug("video_cea_support : %x\n", ini->video_cea_support);
- wfd_sink_debug("video_vesa_support : %x\n", ini->video_vesa_support);
- wfd_sink_debug("video_hh_support : %x\n", ini->video_hh_support);
- wfd_sink_debug("video_profile : %x\n", ini->video_profile);
- wfd_sink_debug("video_level : %x\n", ini->video_level);
- wfd_sink_debug("video_latency : %d\n", ini->video_latency);
- wfd_sink_debug("video_vertical_resolution : %d\n", ini->video_vertical_resolution);
- wfd_sink_debug("video_horizontal_resolution : %d\n", ini->video_horizontal_resolution);
- wfd_sink_debug("video_minimum_slicing : %d\n", ini->video_minimum_slicing);
- wfd_sink_debug("video_slice_enc_param : %d\n", ini->video_slice_enc_param);
- wfd_sink_debug("video_framerate_control_support : %d\n", ini->video_framerate_control_support);
-
- /* hdcp parameter*/
- wfd_sink_debug("hdcp_content_protection : %x\n", ini->hdcp_content_protection);
- wfd_sink_debug("hdcp_port_no : %d\n", ini->hdcp_port_no);
-
- wfd_sink_debug("---------------------------------------------------\n");
-
- loaded = TRUE;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-
-static
-void __mm_wfd_sink_ini_check_status(void)
-{
- struct stat ini_buff;
-
- wfd_sink_debug_fenter();
-
- if (g_stat(MM_WFD_SINK_INI_DEFAULT_PATH, &ini_buff) < 0) {
- wfd_sink_error("failed to get mmfw_wfd_sink ini status\n");
- } else {
- if (ini_buff.st_size < 5) {
- wfd_sink_error("mmfw_wfd_sink.ini file size=%d, Corrupted! So, Removed\n", (int)ini_buff.st_size);
- g_remove(MM_WFD_SINK_INI_DEFAULT_PATH);
- }
- }
-
- wfd_sink_debug_fleave();
-}
-
-int
-mm_wfd_sink_ini_unload(mm_wfd_sink_ini_t *ini)
-{
- wfd_sink_debug_fenter();
-
- loaded = FALSE;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
+++ /dev/null
-installconfiguredir=$(_sysconfdir)/multimedia
-installconfigure_DATA=mmfw_wfd_sink.ini
+++ /dev/null
-# Makefile.in generated by automake 1.10.2 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = config
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-SOURCES =
-DIST_SOURCES =
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
-am__installdirs = "$(DESTDIR)$(installconfiguredir)"
-installconfigureDATA_INSTALL = $(INSTALL_DATA)
-DATA = $(installconfigure_DATA)
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-APPFWK_CFLAGS = @APPFWK_CFLAGS@
-APPFWK_LIBS = @APPFWK_LIBS@
-AR = @AR@
-AUDIOSESSIONMGR_CFLAGS = @AUDIOSESSIONMGR_CFLAGS@
-AUDIOSESSIONMGR_LIBS = @AUDIOSESSIONMGR_LIBS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-ELEMENTARY_CFLAGS = @ELEMENTARY_CFLAGS@
-ELEMENTARY_LIBS = @ELEMENTARY_LIBS@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GLIB_CFLAGS = @GLIB_CFLAGS@
-GLIB_LIBS = @GLIB_LIBS@
-GREP = @GREP@
-GST_APP_CFLAGS = @GST_APP_CFLAGS@
-GST_APP_LIBS = @GST_APP_LIBS@
-GST_CFLAGS = @GST_CFLAGS@
-GST_INTERFACE_CFLAGS = @GST_INTERFACE_CFLAGS@
-GST_INTERFACE_LIBS = @GST_INTERFACE_LIBS@
-GST_LIBS = @GST_LIBS@
-GST_PLUGIN_BASE_CFLAGS = @GST_PLUGIN_BASE_CFLAGS@
-GST_PLUGIN_BASE_LIBS = @GST_PLUGIN_BASE_LIBS@
-INIPARSER_CFLAGS = @INIPARSER_CFLAGS@
-INIPARSER_LIBS = @INIPARSER_LIBS@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-MMCOMMON_CFLAGS = @MMCOMMON_CFLAGS@
-MMCOMMON_LIBS = @MMCOMMON_LIBS@
-MMSESSION_CFLAGS = @MMSESSION_CFLAGS@
-MMSESSION_LIBS = @MMSESSION_LIBS@
-MMSOUND_CFLAGS = @MMSOUND_CFLAGS@
-MMSOUND_LIBS = @MMSOUND_LIBS@
-MMTA_CFLAGS = @MMTA_CFLAGS@
-MMTA_LIBS = @MMTA_LIBS@
-MMUTIL_CFLAGS = @MMUTIL_CFLAGS@
-MMUTIL_LIBS = @MMUTIL_LIBS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-RANLIB = @RANLIB@
-SAVSIMGP_CFLAGS = @SAVSIMGP_CFLAGS@
-SAVSIMGP_LIBS = @SAVSIMGP_LIBS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-lt_ECHO = @lt_ECHO@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-installconfiguredir = /opt/etc
-installconfigure_DATA = mmfw_player.ini
-all: all-am
-
-.SUFFIXES:
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign config/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --foreign config/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-installconfigureDATA: $(installconfigure_DATA)
- @$(NORMAL_INSTALL)
- test -z "$(installconfiguredir)" || $(MKDIR_P) "$(DESTDIR)$(installconfiguredir)"
- @list='$(installconfigure_DATA)'; for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- f=$(am__strip_dir) \
- echo " $(installconfigureDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(installconfiguredir)/$$f'"; \
- $(installconfigureDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(installconfiguredir)/$$f"; \
- done
-
-uninstall-installconfigureDATA:
- @$(NORMAL_UNINSTALL)
- @list='$(installconfigure_DATA)'; for p in $$list; do \
- f=$(am__strip_dir) \
- echo " rm -f '$(DESTDIR)$(installconfiguredir)/$$f'"; \
- rm -f "$(DESTDIR)$(installconfiguredir)/$$f"; \
- done
-tags: TAGS
-TAGS:
-
-ctags: CTAGS
-CTAGS:
-
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
- fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
- else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-am
-all-am: Makefile $(DATA)
-installdirs:
- for dir in "$(DESTDIR)$(installconfiguredir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-am
- -rm -f Makefile
-distclean-am: clean-am distclean-generic
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-info: info-am
-
-info-am:
-
-install-data-am: install-installconfigureDATA
-
-install-dvi: install-dvi-am
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-info: install-info-am
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-ps: install-ps-am
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-installconfigureDATA
-
-.MAKE: install-am install-strip
-
-.PHONY: all all-am check check-am clean clean-generic clean-libtool \
- distclean distclean-generic distclean-libtool distdir dvi \
- dvi-am html html-am info info-am install install-am \
- install-data install-data-am install-dvi install-dvi-am \
- install-exec install-exec-am install-html install-html-am \
- install-info install-info-am install-installconfigureDATA \
- install-man install-pdf install-pdf-am install-ps \
- install-ps-am install-strip installcheck installcheck-am \
- installdirs maintainer-clean maintainer-clean-generic \
- mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
- ps ps-am uninstall uninstall-am uninstall-installconfigureDATA
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
AC_PREREQ(2.61)
AC_INIT([libmm-wfd],[0.0.1])
-AC_CONFIG_SRCDIR([sink/mm_wfd_sink_priv.c])
+AC_CONFIG_SRCDIR([src/mm_wfd_sink_priv.c])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AM_CONDITIONAL([IS_SDK], [test "x$IS_SDK" = "xyes"])
AC_CONFIG_FILES([Makefile
- common/Makefile
- sink/Makefile
- mm-wfd.pc
+ src/Makefile
+ mm-wfd.pc
])
AC_OUTPUT
Name: libmm-wfd
Summary: Multimedia Framework Wifi-Display Library
-Version: 0.2.195
+Version: 0.2.196
Release: 0
Group: System/Libraries
License: Apache-2.0
%defattr(-,root,root,-)
%{_libdir}/*.so
%{_includedir}/mmf/mm_wfd_sink.h
+%{_includedir}/mmf/mm_wfd_sink_priv.h
+%{_includedir}/mmf/mm_wfd_sink_dlog.h
+%{_includedir}/mmf/mm_wfd_sink_util.h
+%{_includedir}/mmf/mm_wfd_sink_ini.h
+%{_includedir}/mmf/mm_wfd_sink_attrs.h
%{_libdir}/pkgconfig/*
#%files factory
+++ /dev/null
-lib_LTLIBRARIES = libmmfwfdsink.la
-
-includelibmmfwfdsinkdir = $(includedir)/mmf
-
-includelibmmfwfdsink_HEADERS = include/mm_wfd_sink.h
-
-libmmfwfdsink_la_SOURCES = mm_wfd_sink_util.c \
- mm_wfd_sink.c \
- mm_wfd_sink_manager.c \
- mm_wfd_sink_priv.c \
- mm_wfd_sink_wayland.c
-
-
-libmmfwfdsink_la_CFLAGS = -I$(srcdir)/include \
- $(MMCOMMON_CFLAGS) \
- $(GST_CFLAGS) \
- $(EVAS_CFLAGS) \
- $(ELEMENTARY_CFLAGS) \
- $(GST_PLUGINS_BASE_CFLAGS) \
- $(GST_VIDEO_CFLAGS) \
- $(MM_WFD_COMMON_CFLAGS) \
- $(AUDIOSESSIONMGR_CFLAGS) \
- $(TZPLATFORM_CONFIG_CFLAGS) \
- -I$(top_builddir)/common/include
-
-
-libmmfwfdsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-
-noinst_HEADERS = include/mm_wfd_sink_priv.h \
- include/mm_wfd_sink_util.h \
- include/mm_wfd_sink_manager.h \
- include/mm_wfd_sink_wayland.h
-
-libmmfwfdsink_la_LIBADD = $(GST_LIBS) \
- $(GST_PLUGINS_BASE_LIBS) \
- $(GST_BASE_LIBS) \
- $(ELEMENTARY_LIBS) \
- $(EVAS_LIBS) \
- $(top_builddir)/common/libwfdcommon.la \
- $(MMCOMMON_LIBS) \
- $(MM_WFD_COMMON_LIBS) \
- $(AUDIOSESSIONMGR_LIBS) \
- $(TZPLATFORM_CONFIG_LIBS) \
- $(GST_VIDEO_LIBS)
-
-
-libmmfwfdsink_la_CFLAGS += $(MMLOG_CFLAGS) -DMMF_LOG_OWNER=0x02000000 -DMMF_DEBUG_PREFIX=\"MMF-WFD-SINK\"
-libmmfwfdsink_la_LIBADD += $(MMLOG_LIBS)
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef _MM_WFD_SINK_H_
-#define _MM_WFD_SINK_H_
-
-#include <string.h>
-#include <glib.h>
-#include <mm_message.h>
-#include <mm_error.h>
-#include <mm_types.h>
-
-/**
- * * Enumerations of wifi-display sink state.
- * */
-typedef enum {
- MM_WFD_SINK_STATE_NONE, /**< wifi-display is not created */
- MM_WFD_SINK_STATE_NULL, /**< wifi-display is created */
- MM_WFD_SINK_STATE_PREPARED, /**< wifi-display is prepared */
- MM_WFD_SINK_STATE_CONNECTED, /**< wifi-display is connected */
- MM_WFD_SINK_STATE_PLAYING, /**< wifi-display is now playing */
- MM_WFD_SINK_STATE_PAUSED, /**< wifi-display is now paused */
- MM_WFD_SINK_STATE_DISCONNECTED, /**< wifi-display is disconnected */
- MM_WFD_SINK_STATE_NUM, /**< Number of wifi-display states */
-} MMWFDSinkStateType;
-
-/* audio codec : AAC, AC3, LPCM */
-typedef enum {
- MM_WFD_SINK_AUDIO_CODEC_NONE,
- MM_WFD_SINK_AUDIO_CODEC_AAC = 0x0F,
- MM_WFD_SINK_AUDIO_CODEC_AC3 = 0x81,
- MM_WFD_SINK_AUDIO_CODEC_LPCM = 0x83
-} MMWFDSinkAudioCodec;
-
-/* video codec : H264 */
-typedef enum {
- MM_WFD_SINK_VIDEO_CODEC_NONE,
- MM_WFD_SINK_VIDEO_CODEC_H264 = 0x1b
-} MMWFDSinkVideoCodec;
-
-typedef void(*MMWFDMessageCallback)(int error_type, MMWFDSinkStateType state_type, void *user_data);
-
-/**
- * This function creates a wi-fi display sink object. \n
- * The attributes of wi-fi display sink are created to get/set some values with application. \n
- * And, mutex, gstreamer and other resources are initialized at this time. \n
- * If wi-fi display sink is created, he state will become MM_WFD_SINK_STATE_NULL.. \n
- *
- * @param wfd_sink [out] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code. \n
- * Please refer 'mm_error.h' to know it in detail.
- * @pre None
- * @post MM_WFD_SINK_STATE_NULL
- * @see mm_wfd_sink_destroy
- * @remark You can create multiple handles on a context at the same time. \n
- * However, wi-fi display sink cannot guarantee proper operation because of limitation of resources, \n
- * such as audio device or display device.
- *
- * @par Example
- * @code
-if (mm_wfd_sink_create(&g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to create wi-fi display sink\n");
-}
-
-mm_wfd_sink_set_message_callback(g_wfd_sink, msg_callback, (void*)g_wfd_sink);
- * @endcode
- */
-int mm_wfd_sink_create(MMHandleType *wfd_sink);
-
-/**
- * This function trys to make gstreamer pipeline. \n
- * If wi-fi display sink is realized, the state will become MM_WFD_SINK_STATE_READY.. \n
- *
- * @param wfd_sink [out] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code. \n
- * Please refer 'mm_error.h' to know it in detail.
- * @pre MM_WFD_SINK_STATE_NULL
- * @post MM_WFD_SINK_STATE_PREPARED
- * @see mm_wfd_sink_unprepare
- * @remark None
- * @par Example
- * @code
-if (mm_wfd_sink_prepare(&g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to realize wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_prepare(MMHandleType wfd_sink);
-
-/**
- * This function connect wi-fi display source using uri. \n
- * audio type(AC3 AAC, LPCM) is decided at this time. \n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param uri [in] URI of wi-fi displaysource to be connected
- *
- * @return This function returns zero on success, or negative value with error code.
- *
- * @pre wi-fi display sink state should be MM_WFD_SINK_STATE_PREPARED
- * @post wi-fi display sink state will be MM_WFD_SINK_STATE_CONNECTED with no preroll.
- * @remark None
- * @par Example
- * @code
-if (mm_wfd_sink_connect(g_wfd_sink, g_uri) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to connect to wi-fi display source\n");
-}
- * @endcode
- */
-int mm_wfd_sink_connect(MMHandleType wfd_sink, const char *uri);
-
-/**
- * This function is to start playing. \n
- * Data from wi-fi display source will be received. \n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code.
- * @remark
- *
- * @pre wi-fi display sink state may be MM_WFD_SINK_STATE_CONNECTED.
- * @post wi-fi display sink state will be MM_WFD_SINK_STATE_PLAYING.
- * @see mm_wfd_sink_disconnect
- * @remark None
- * @par Example
- * @code
-if (mm_wfd_sink_start(g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to start wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_start(MMHandleType wfd_sink);
-
-/**
- * This function is to pause playing. \n
- * The wi-fi display sink pause the current stream being received form wi-fi display source. \n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code.
- * @remark
- *
- * @pre wi-fi display sink state should be MM_WFD_SINK_STATE_PLAYING.
- * @post wi-fi display sink state will be MM_WFD_SINK_STATE_PAUSED.
- * @see mm_wfd_sink_pause
- * @remark None
- * @par Example
- * @code
-if (mm_wfd_sink_pause(g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to pause wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_pause(MMHandleType wfd_sink);
-
-/**
- * This function is to resume playing. \n
- * Data from wi-fi display source will be received. \n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code.
- * @remark
- *
- * @pre wi-fi display sink state may be MM_WFD_SINK_STATE_PAUSED.
- * @post wi-fi display sink state will be MM_WFD_SINK_STATE_PLAYING.
- * @see mm_wfd_sink_disconnect
- * @remark None
- * @par Example
- * @code
-if (mm_wfd_sink_start(g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to resume wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_resume(MMHandleType wfd_sink);
-
-/**
- * This function is to stop playing wi-fi display. \n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code.
- *
- * @pre wi-fi display sink state may be MM_WFD_SINK_STATE_PLAYING.
- * @post wi-fi display sink state will be MM_WFD_SINK_STATE_DISCONNECTED.
- * @see mm_wfd_sink_start
- * @remark None
- * @par Example
- * @code
-if (mm_wfd_sink_disconnect(g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to stop wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_disconnect(MMHandleType wfd_sink);
-
-/**
- * This function trys to destroy gstreamer pipeline. \n
- *
- * @param wfd_sink [out] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code. \n
- * Please refer 'mm_error.h' to know it in detail.
- * @pre wi-fi display sink state may be MM_WFD_SINK_STATE_PREPARED or MM_WFD_SINK_STATE_DISCONNECTED.
- * But, it can be called in any state.
- * @post MM_WFD_SINK_STATE_NULL
- * @see mm_wfd_sink_prepare
- * @remark None
- * @par Example
- * @code
-if (mm_wfd_sink_unprepare(&g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to unprepare wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_unprepare(MMHandleType wfd_sink);
-
-/**
- * This function releases wi-fi display sink object and all resources which were created by mm_wfd_sink_create(). \n
- * And, wi-fi display sink handle will also be destroyed. \n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state may be MM_WFD_SINK_STATE_NULL. \n
- * But, it can be called in any state.
- * @post Because handle is released, there is no any state.
- * @see mm_wfd_sink_create
- * @remark This method can be called with a valid wi-fi display sink handle from any state to \n
- * completely shutdown the wi-fi display sink operation.
- *
- * @par Example
- * @code
-if (mm_wfd_sink_destroy(g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to destroy wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_destroy(MMHandleType wfd_sink);
-
-/**
- * This function sets callback function for receiving messages from wi-fi display sink. \n
- * So, player can notify warning, error and normal cases to application. \n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param callback [in] Message callback function.
- * @param user_param [in] User parameter which is passed to callback function.
- *
- * @return This function returns zero on success, or negative value with error code.
- * @see MMWFDMessageCallback
- * @remark None
- * @par Example
- * @code
-
-int msg_callback(int error_type, MMWFDSinkStateType state_type, void *user_data)
-{
- switch (state_type)
- {
- case MM_WFD_SINK_STATE_NULL:
- //do something
- break;
-
- case MM_WFD_SINK_STATE_PREPARED:
- //do something
- break;
-
- case MM_WFD_SINK_STATE_CONNECTED:
- //do something
- break;
-
- case MM_WFD_SINK_STATE_PLAYING:
- //do something
- break;
-
- case MM_WFD_SINK_STATE_PAUSED:
- //do something
- break;
-
- case MM_WFD_SINK_DISCONNECTED:
- //do something
- break;
-
- default:
- break;
- }
- return TRUE;
-}
-
-mm_wfd_sink_set_message_callback(g_wfd_sink, msg_callback, (void*)g_wfd_sink);
- * @endcode
- */
-int mm_wfd_sink_set_message_callback(MMHandleType wfd_sink, MMWFDMessageCallback callback, void *user_param);
-
-int mm_wfd_sink_set_attribute(MMHandleType wfd_sink, char **err_attr_name, const char *first_attribute_name, ...);
-
-/**
- * This function get resources \n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state should be MM_WFD_SINK_STATE_READY or MM_WFD_SINK_STATE_PREPARED. \n
- * @post N/A
- * @remark resources are released when mm_wfd_sink_destory is called
- *
- * @par Example
- * @code
-if (mm_wfd_sink_get_resource(g_wfd_sink) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to get resources for wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_get_resource(MMHandleType wfd_sink);
-
-/**
- * This function sets the display surface type for wi-fi display sink\n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param display_surface_type [in] Display surface type
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
- *
- * @par Example
- * @code
-if (mm_wfd_sink_set_display_surface_type(g_wfd_sink, g_display_surface_type) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to set display surface type for wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_set_display_surface_type(MMHandleType wfd_sink, gint display_surface_type);
-
-/**
- * This function sets the display overlay for wi-fi display sink\n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param display_overlay [in] Display overlay
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
- *
- * @par Example
- * @code
-if (mm_wfd_sink_set_display_overlay(g_wfd_sink, g_display_overlay) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to set display overlay for wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_set_display_overlay(MMHandleType wfd_sink, void *display_overlay);
-
-/**
- * This function sets the display method for wi-fi display sink\n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param display_method [in] Display method
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
- *
- * @par Example
- * @code
-if (mm_wfd_sink_set_display_method(g_wfd_sink, g_display_method) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to set display method for wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_set_display_method(MMHandleType wfd_sink, gint display_method);
-
-/**
- * This function sets the display visible for wi-fi display sink\n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param display_visible [in] Display visible
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
- *
- * @par Example
- * @code
-if (mm_wfd_sink_set_display_visible(g_wfd_sink, g_display_visible) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to set display visible for wi-fi display sink\n");
-}
- * @endcode
- */
-int mm_wfd_sink_set_display_visible(MMHandleType wfd_sink, gint display_visible);
-
-/**
- * This function gets the width and height of video which is played by wi-fi display sink\n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param width [in] Width of video
- * @param height [in] Height of video
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state should be MM_WFD_SINK_STATE_CONNECTED or MM_WFD_SINK_STATE_PLAYING. \n
- *
- * @par Example
- * @code
-gint g_width=0, g_height=0;
-
-if (mm_wfd_sink_get_video_resolution(g_wfd_sink, &g_width, &g_height) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to get video resolution.\n");
-}
- * @endcode
- */
-int mm_wfd_sink_get_video_resolution(MMHandleType wfd_sink, gint *width, gint *height);
-
-/**
- * This function gets the width and height of video which is played by wi-fi display sink\n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param framerate [in] Framerate of video
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state should be MM_WFD_SINK_STATE_CONNECTED or MM_WFD_SINK_STATE_PLAYING. \n
- *
- * @par Example
- * @code
-gint g_framerate=0;
-
-if (mm_wfd_sink_get_video_framerate(g_wfd_sink, &g_framerate) != MM_ERROR_NONE)
-{
- wfd_sink_error("failed to get video framerate.\n");
-}
- * @endcode
- */
-int mm_wfd_sink_get_video_framerate(MMHandleType wfd_sink, gint *framerate);
-
-/**
- * This function sets the resolutions for wi-fi display sink\n
- *
- * @param wfd_sink [in] Handle of wi-fi display sink
- * @param resolution [in] Resolutions for wi-fi display sink
- *
- * @return This function returns zero on success, or negative value with error code.
- * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
- *
- */
-int mm_wfd_sink_set_resolution(MMHandleType wfd_sink, gint resolution);
-
-int mm_wfd_sink_get_negotiated_video_codec(MMHandleType wfd_sink, gint *codec);
-int mm_wfd_sink_get_negotiated_video_resolution(MMHandleType wfd_sink, gint *width, gint *height);
-int mm_wfd_sink_get_negotiated_video_frame_rate(MMHandleType wfd_sink, gint *frame_rate);
-int mm_wfd_sink_get_negotiated_audio_codec(MMHandleType wfd_sink, gint *codec);
-int mm_wfd_sink_get_negotiated_audio_channel(MMHandleType wfd_sink, gint *channel);
-int mm_wfd_sink_get_negotiated_audio_sample_rate(MMHandleType wfd_sink, gint *sample_rate);
-int mm_wfd_sink_get_negotiated_audio_bitwidth(MMHandleType wfd_sink, gint *bitwidth);
-#endif
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
- * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef __MM_WFD_SINK_MANAGER_H__
-#define __MM_WFD_SINK_MANAGER_H__
-
-/*=======================================================================================
-| INCLUDE FILES |
-========================================================================================*/
-#include "mm_wfd_sink_priv.h"
-#include "mm_wfd_sink_util.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WFD_SINK_MANAGER_LOCK(wfd_sink) \
- do {\
- if (wfd_sink) {\
- g_mutex_lock(&((wfd_sink)->manager_thread_mutex));\
- }\
- } while (0);
-
-#define WFD_SINK_MANAGER_UNLOCK(wfd_sink) \
- do {\
- if (wfd_sink) {\
- g_mutex_unlock(&((wfd_sink)->manager_thread_mutex));\
- }\
- } while (0);
-
-#define WFD_SINK_MANAGER_WAIT_CMD(wfd_sink) \
- do {\
- if (wfd_sink->manager_thread_exit == FALSE) {\
- wfd_sink_debug("manager thread is waiting for command signal");\
- wfd_sink->waiting_cmd = TRUE; \
- g_cond_wait(&((wfd_sink)->manager_thread_cond), &((wfd_sink)->manager_thread_mutex)); \
- wfd_sink->waiting_cmd = FALSE; \
- } else {\
- wfd_sink_debug("manager thread is stopped, don't need to wait for command signal");\
- }\
- } while (0);
-
-#define WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, cmd) \
- do {\
- WFD_SINK_MANAGER_LOCK(wfd_sink);\
- if (cmd == WFD_SINK_MANAGER_CMD_EXIT) {\
- g_list_free(wfd_sink->manager_thread_cmd);\
- wfd_sink->manager_thread_cmd = NULL;\
- wfd_sink->manager_thread_exit = TRUE;\
- }\
- wfd_sink->manager_thread_cmd = g_list_append(wfd_sink->manager_thread_cmd, GINT_TO_POINTER(cmd)); \
- WFD_SINK_MANAGER_UNLOCK(wfd_sink);\
- } while (0);
-
-#define WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink) \
- do {\
- WFD_SINK_MANAGER_LOCK(wfd_sink);\
- if (wfd_sink->waiting_cmd) {\
- if (wfd_sink->manager_thread_cmd) {\
- wfd_sink_debug("send command signal to manager thread");\
- g_cond_signal(&((wfd_sink)->manager_thread_cond));\
- }\
- }\
- WFD_SINK_MANAGER_UNLOCK(wfd_sink);\
- } while (0);
-
-/**
- * This function is to initialize manager
- *
- * @param[in] handle Handle of wfd_sink.
- * @return This function returns zero on success, or negative value with errors.
- * @remarks
- * @see
- *
- */
-int _mm_wfd_sink_init_manager(mm_wfd_sink_t *wfd_sink);
-/**
- * This function is to release manager
- *
- * @param[in] handle Handle of wfd_sink.
- * @return This function returns zero on success, or negative value with errors.
- * @remarks
- * @see
- *
- */
-int _mm_wfd_sink_release_manager(mm_wfd_sink_t *wfd_sink);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef _MM_WFD_SINK_PRIV_H_
-#define _MM_WFD_SINK_PRIV_H_
-
-#include <string.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <gst/gst.h>
-#include <mm_types.h>
-#include <mm_attrs.h>
-#include <mm_message.h>
-#include <mm_error.h>
-#include <mm_types.h>
-#include <mm_wfd_sink_ini.h>
-#include <mm_wfd_attrs.h>
-
-#include "mm_wfd_sink.h"
-
-/* main pipeline's element id */
-enum WFDSinkMainElementID {
- WFD_SINK_M_PIPE = 0, /* NOTE : WFD_SINK_M_PIPE should be zero */
- WFD_SINK_M_SRC,
- WFD_SINK_M_DEPAY,
- WFD_SINK_M_DEMUX,
- WFD_SINK_M_NUM
-};
-
-/* audio decodebin's element id */
-enum WFDSinkAudioDecodeBinElementID {
- WFD_SINK_A_D_BIN = 0, /* NOTE : WFD_SINK_A_D_BIN should be zero */
- WFD_SINK_A_D_QUEUE,
- WFD_SINK_A_D_HDCP,
- WFD_SINK_A_D_AAC_PARSE,
- WFD_SINK_A_D_AAC_DEC,
- WFD_SINK_A_D_AC3_PARSE,
- WFD_SINK_A_D_AC3_DEC,
- WFD_SINK_A_D_LPCM_CONVERTER,
- WFD_SINK_A_D_LPCM_FILTER,
- WFD_SINK_A_D_NUM
-};
-
-/* audio sinkbin's element id */
-enum WFDSinkAudioSinkBinElementID {
- WFD_SINK_A_S_BIN = 0, /* NOTE : WFD_SINK_A_S_BIN should be zero */
- WFD_SINK_A_S_RESAMPLER,
- WFD_SINK_A_S_VOLUME,
- WFD_SINK_A_S_SINK,
- WFD_SINK_A_S_NUM
-};
-
-/* video decodebin's element id */
-enum WFDSinkVideoDecodeBinElementID {
- WFD_SINK_V_D_BIN = 0, /* NOTE : WFD_SINK_V_D_BIN should be zero */
- WFD_SINK_V_D_QUEUE,
- WFD_SINK_V_D_HDCP,
- WFD_SINK_V_D_PARSE,
- WFD_SINK_V_D_CAPSSETTER,
- WFD_SINK_V_D_DEC,
- WFD_SINK_V_D_NUM
-};
-
-/* video sinkbin's element id */
-enum WFDSinkVideoSinkBinElementID {
- WFD_SINK_V_S_BIN = 0, /* NOTE : WFD_SINK_V_S_BIN should be zero */
- WFD_SINK_V_S_CONVERT,
- WFD_SINK_V_S_FILTER,
- WFD_SINK_V_S_SINK,
- WFD_SINK_V_S_NUM
-};
-
-/**
- * * Enumerations of wifi-display command.
- * */
-typedef enum {
- MM_WFD_SINK_COMMAND_NONE, /**< command for nothing */
- MM_WFD_SINK_COMMAND_CREATE, /**< command for creating wifi-display sink */
- MM_WFD_SINK_COMMAND_PREPARE, /**< command for preparing wifi-display sink */
- MM_WFD_SINK_COMMAND_CONNECT, /**< command for connecting wifi-display sink */
- MM_WFD_SINK_COMMAND_START, /**< command for starting wifi-display sink */
- MM_WFD_SINK_COMMAND_PAUSE, /**< command for pausing wifi-display sink */
- MM_WFD_SINK_COMMAND_RESUME, /**< command for resuming wifi-display sink */
- MM_WFD_SINK_COMMAND_DISCONNECT, /**< command for disconnecting wifi-display sink */
- MM_WFD_SINK_COMMAND_UNPREPARE, /**< command for unpreparing wifi-display sink */
- MM_WFD_SINK_COMMAND_DESTROY, /**< command for destroting wifi-display sink */
- MM_WFD_SINK_COMMAND_NUM, /**< Number of wifi-display commands */
-} MMWFDSinkCommandType;
-
-/**
- * * Enumerations of thread command.
- * */
-typedef enum {
- WFD_SINK_MANAGER_CMD_NONE = 0,
- WFD_SINK_MANAGER_CMD_LINK_A_DECODEBIN,
- WFD_SINK_MANAGER_CMD_LINK_V_DECODEBIN,
- WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE,
- WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE,
- WFD_SINK_MANAGER_CMD_EXIT,
-} WFDSinkManagerCMDType;
-
-/**
- * * Enumerations of resolution.
- * */
-typedef enum {
- MM_WFD_SINK_RESOLUTION_UNKNOWN = 0,
- MM_WFD_SINK_RESOLUTION_1920x1080_P30 = (1 << 0), /**< W-1920, H-1080, 30 fps*/
- MM_WFD_SINK_RESOLUTION_1280x720_P30 = (1 << 1), /**< W-1280, H-720, 30 fps*/
- MM_WFD_SINK_RESOLUTION_960x540_P30 = (1 << 2), /**< W-960, H-540, 30 fps*/
- MM_WFD_SINK_RESOLUTION_864x480_P30 = (1 << 3), /**< W-864, H-480, 30 fps*/
- MM_WFD_SINK_RESOLUTION_720x480_P60 = (1 << 4), /**< W-720, H-480, 30 fps*/
- MM_WFD_SINK_RESOLUTION_640x480_P60 = (1 << 5), /**< W-640, H-480, 60 fps*/
- MM_WFD_SINK_RESOLUTION_640x360_P30 = (1 << 6), /**< W-640, H-360, 30 fps*/
- MM_WFD_SINK_RESOLUTION_MAX = 128,
-} MMWFDSinkResolution;
-
-typedef struct {
- gint codec;
- gint width;
- gint height;
- gint frame_rate;
-} MMWFDSinkVideoStreamInfo;
-
-typedef struct {
- gint codec;
- gint channels;
- gint sample_rate;
- gint bitwidth;
-} MMWFDSinkAudioStreamInfo;
-
-typedef struct {
- MMWFDSinkAudioStreamInfo audio_stream_info;
- MMWFDSinkVideoStreamInfo video_stream_info;
-} MMWFDSinkStreamInfo;
-
-
-typedef struct {
- gint id;
- GstElement *gst;
-} MMWFDSinkGstElement;
-
-typedef struct {
- MMWFDSinkGstElement *mainbin;
- MMWFDSinkGstElement *a_decodebin;
- MMWFDSinkGstElement *v_decodebin;
- MMWFDSinkGstElement *a_sinkbin;
- MMWFDSinkGstElement *v_sinkbin;
-} MMWFDSinkGstPipelineInfo;
-
-typedef struct {
- MMWFDSinkStateType state; /* wfd current state */
- MMWFDSinkStateType prev_state; /* wfd previous state */
- MMWFDSinkStateType pending_state; /* wfd state which is going to now */
-} MMWFDSinkState;
-
-#define MMWFDSINK_GET_ATTRS(x_wfd) ((x_wfd)? ((mm_wfd_sink_t*)x_wfd)->attrs : (MMHandleType)NULL)
-
-typedef struct {
- /* gstreamer pipeline */
- MMWFDSinkGstPipelineInfo *pipeline;
- gboolean audio_decodebin_is_linked;
- gboolean video_decodebin_is_linked;
-
- /* timestamp compensation */
- gboolean need_to_reset_basetime;
-
- GstClock *clock;
- gint64 video_average_gap;
- gint64 video_accumulated_gap;
- gint64 video_buffer_count;
- gint64 audio_average_gap;
- gint64 audio_accumulated_gap;
- gint64 audio_buffer_count;
- GstClockTime last_buffer_timestamp;
-
- /* attributes */
- MMHandleType attrs;
-
- /* state */
- MMWFDSinkState state;
-
- /* initialize values */
- mm_wfd_sink_ini_t ini;
-
- /* command */
- MMWFDSinkCommandType cmd;
- GMutex cmd_lock;
- gboolean waiting_cmd;
-
- /* stream information */
- MMWFDSinkStreamInfo stream_info;
-
- /* Message handling */
- MMWFDMessageCallback msg_cb;
- void *msg_user_data;
-
- /* video resolution for negotiation */
- MMWFDSinkResolution supportive_resolution;
-
- GThread *manager_thread;
- GMutex manager_thread_mutex;
- GCond manager_thread_cond;
- GList *manager_thread_cmd;
- gboolean manager_thread_exit;
-} mm_wfd_sink_t;
-
-
-int _mm_wfd_sink_create(mm_wfd_sink_t **wfd_sink);
-int _mm_wfd_sink_destroy(mm_wfd_sink_t *wfd_sink);
-int _mm_wfd_sink_prepare(mm_wfd_sink_t *wfd_sink);
-int _mm_wfd_sink_unprepare(mm_wfd_sink_t *wfd_sink);
-int _mm_wfd_sink_connect(mm_wfd_sink_t *wfd_sink, const char *uri);
-int _mm_wfd_sink_disconnect(mm_wfd_sink_t *wfd_sink);
-int _mm_wfd_sink_start(mm_wfd_sink_t *wfd_sink);
-int _mm_wfd_sink_pause(mm_wfd_sink_t *wfd_sink);
-int _mm_wfd_sink_resume(mm_wfd_sink_t *wfd_sink);
-int _mm_wfd_set_message_callback(mm_wfd_sink_t *wfd_sink, MMWFDMessageCallback callback, void *user_data);
-int _mm_wfd_sink_get_resource(mm_wfd_sink_t *wfd_sink);
-int _mm_wfd_sink_set_resolution(mm_wfd_sink_t *wfd_sink, MMWFDSinkResolution resolution);
-
-int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink);
-int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink);
-int __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink);
-int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink);
-
-const gchar *_mm_wfds_sink_get_state_name(MMWFDSinkStateType state);
-
-#endif
-
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef _MM_WFD_SINK_UTIL_H_
-#define _MM_WFD_SINK_UTIL_H_
-
-#include <glib.h>
-#include <gst/gst.h>
-#include <mm_message.h>
-#include <mm_error.h>
-#include <mm_types.h>
-#include "mm_wfd_sink_dlog.h"
-
-#define MMWFDSINK_FREEIF(x) \
- do {\
- if ((x)) \
- g_free((gpointer)(x)); \
- (x) = NULL;\
- } while (0);
-
-/* lock for commnad */
-#define MMWFDSINK_CMD_LOCK(x_wfd) \
- if (x_wfd) \
- g_mutex_lock(&(((mm_wfd_sink_t *)x_wfd)->cmd_lock));
-
-#define MMWFDSINK_CMD_UNLOCK(x_wfd) \
- if (x_wfd) \
- g_mutex_unlock(&(((mm_wfd_sink_t *)x_wfd)->cmd_lock));
-
-/* create element */
-#define MMWFDSINK_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket) \
- do { \
- if (x_name && (strlen(x_factory) > 1)) {\
- x_bin[x_id].id = x_id;\
- x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
- if (! x_bin[x_id].gst) {\
- wfd_sink_error("failed to create %s \n", x_factory);\
- goto CREATE_ERROR;\
- }\
- wfd_sink_debug("%s is created \n", x_factory);\
- if (x_add_bucket)\
- element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
- }\
- } while (0);
-
-/* generating dot */
-#define MMWFDSINK_GENERATE_DOT_IF_ENABLED(x_wfd_sink, x_name) \
- if (x_wfd_sink->ini.generate_dot) { \
- wfd_sink_debug("create dot file : %s.dot", x_name);\
- GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(x_wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst), \
- GST_DEBUG_GRAPH_SHOW_ALL, x_name); \
- }
-
-/* postint message */
-#define MMWFDSINK_POST_MESSAGE(x_wfd_sink, x_error_type, x_state_type) \
- if (x_wfd_sink->msg_cb) { \
- wfd_sink_debug("Message(error : %d, state : %d) will be posted using user callback\n", x_error_type, x_state_type); \
- x_wfd_sink->msg_cb(x_error_type, x_state_type, x_wfd_sink->msg_user_data); \
- }
-
-
-/* state */
-#define MMWFDSINK_CURRENT_STATE(x_wfd_sink) ((mm_wfd_sink_t *)x_wfd_sink)->state.state
-#define MMWFDSINK_PREVIOUS_STATE(x_wfd_sink) ((mm_wfd_sink_t *)x_wfd_sink)->state.prev_state
-#define MMWFDSINK_PENDING_STATE(x_wfd_sink) ((mm_wfd_sink_t *)x_wfd_sink)->state.pending_state
-#define MMWFDSINK_STATE_GET_NAME(x_state) _mm_wfds_sink_get_state_name(x_state)
-
-#define MMWFDSINK_PRINT_STATE(x_wfd_sink) \
- wfd_sink_debug("--prev %s, current %s, pending %s--\n", \
- MMWFDSINK_STATE_GET_NAME(MMWFDSINK_PREVIOUS_STATE(x_wfd_sink)), \
- MMWFDSINK_STATE_GET_NAME(MMWFDSINK_CURRENT_STATE(x_wfd_sink)), \
- MMWFDSINK_STATE_GET_NAME(MMWFDSINK_PENDING_STATE(x_wfd_sink)));
-
-#define MMWFDSINK_CHECK_STATE(x_wfd_sink, x_cmd) \
- switch (__mm_wfd_sink_check_state((mm_wfd_sink_t *)x_wfd_sink, x_cmd)) \
- { \
- case MM_ERROR_NONE: \
- break;\
- case MM_ERROR_WFD_NO_OP: \
- return MM_ERROR_NONE; \
- break; \
- default: \
- return MM_ERROR_WFD_INVALID_STATE; \
- break; \
- }
-
-
-/* pad probe */
-void
-mm_wfd_sink_util_add_pad_probe(GstPad *pad, GstElement *element, const gchar *pad_name);
-void
-mm_wfd_sink_util_add_pad_probe_for_checking_first_buffer(GstPad *pad, GstElement *element, const gchar *pad_name);
-
-#define MMWFDSINK_PAD_PROBE(x_wfd_sink, x_pad, x_element, x_pad_name) \
- if (x_wfd_sink) { \
- if (x_wfd_sink->ini.enable_pad_probe) { \
- mm_wfd_sink_util_add_pad_probe(x_pad, x_element, (const gchar*)x_pad_name); \
- } else {\
- mm_wfd_sink_util_add_pad_probe_for_checking_first_buffer (x_pad, x_element, (const gchar*)x_pad_name); \
- }\
- }
-
-void
-mm_wfd_sink_util_add_pad_probe_for_data_dump(GstElement *element, const gchar *pad_name);
-
-#define MMWFDSINK_TS_DATA_DUMP(x_wfd_sink, x_element, x_pad_name) \
- if (x_wfd_sink && x_wfd_sink->ini.enable_ts_data_dump) { \
- mm_wfd_sink_util_add_pad_probe_for_data_dump (x_element, (const gchar*)x_pad_name); \
- }
-
-#endif
+++ /dev/null
-/*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-
-#ifndef __MM_WFD_SINK_WLCLIENT_H__
-#define __MM_WFD_SINK_WLCLIENT_H__
-#include <stdio.h>
-#include <tbm_bufmgr.h>
-#include <tizen-extension-client-protocol.h>
-#include <wayland-client.h>
-#include <mm_types.h>
-#include <mm_debug.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef struct
-{
- struct wl_display *display;
- struct wl_registry *registry;
- struct tizen_surface *tz_surface;
- struct tizen_resource *tz_resource;
-} wl_client;
-
-int mm_wfd_sink_wlclient_create (wl_client ** wlclient);
-int mm_wfd_sink_wlclient_get_wl_window_wl_surface_id (wl_client * wlclient, struct wl_surface *surface, struct wl_display *display);
-void mm_wfd_sink_wlclient_finalize (wl_client * wlclient);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MM_WFD_SINK_WLCLIENT_H__ */
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <gst/gst.h>
-
-#include "mm_wfd_sink_util.h"
-#include "mm_wfd_sink.h"
-#include "mm_wfd_sink_priv.h"
-#include "mm_wfd_sink_dlog.h"
-
-int mm_wfd_sink_create(MMHandleType *wfd_sink)
-{
- mm_wfd_sink_t *new_wfd_sink = NULL;
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- result = _mm_wfd_sink_create(&new_wfd_sink);
- if (result != MM_ERROR_NONE) {
- wfd_sink_error("fail to create wi-fi display sink handle. ret[%d]", result);
- *wfd_sink = (MMHandleType)NULL;
- return result;
- }
-
- /* init wfd lock */
- g_mutex_init(&new_wfd_sink->cmd_lock);
-
- *wfd_sink = (MMHandleType)new_wfd_sink;
-
- wfd_sink_debug_fleave();
-
- return result;
-
-}
-
-int mm_wfd_sink_prepare(MMHandleType wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_prepare((mm_wfd_sink_t *)wfd_sink);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_connect(MMHandleType wfd_sink, const char *uri)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(uri, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_connect((mm_wfd_sink_t *)wfd_sink, uri);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_start(MMHandleType wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_start((mm_wfd_sink_t *)wfd_sink);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_pause(MMHandleType wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_pause((mm_wfd_sink_t *)wfd_sink);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_resume(MMHandleType wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_resume((mm_wfd_sink_t *)wfd_sink);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_disconnect(MMHandleType wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_disconnect((mm_wfd_sink_t *)wfd_sink);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_unprepare(MMHandleType wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_unprepare((mm_wfd_sink_t *)wfd_sink);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_destroy(MMHandleType wfd_sink)
-{
- int result = MM_ERROR_NONE;
- mm_wfd_sink_t *sink_handle = NULL;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_destroy((mm_wfd_sink_t *)wfd_sink);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- g_mutex_clear(&(((mm_wfd_sink_t *)wfd_sink)->cmd_lock));
-
- sink_handle = (mm_wfd_sink_t *)wfd_sink;
- MMWFDSINK_FREEIF(sink_handle);
-
- return result;
-}
-
-int mm_wfd_sink_set_message_callback(MMHandleType wfd_sink, MMWFDMessageCallback callback, void *user_data)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_set_message_callback((mm_wfd_sink_t *)wfd_sink, callback, user_data);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_set_attribute(MMHandleType wfd_sink, char **err_attr_name, const char *first_attribute_name, ...)
-{
- int result = MM_ERROR_NONE;
- va_list var_args;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(first_attribute_name, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd_sink);
- va_start(var_args, first_attribute_name);
- result = _mmwfd_set_attribute(MMWFDSINK_GET_ATTRS(wfd_sink), err_attr_name, first_attribute_name, var_args);
- va_end(var_args);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_get_video_resolution(MMHandleType wfd_sink, gint *width, gint *height)
-{
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(width, MM_ERROR_WFD_INVALID_ARGUMENT);
- wfd_sink_return_val_if_fail(height, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- *width = wfd->stream_info.video_stream_info.width;
- *height = wfd->stream_info.video_stream_info.height;
-
- return MM_ERROR_NONE;
-}
-
-int mm_wfd_sink_get_video_framerate(MMHandleType wfd_sink, gint *frame_rate)
-{
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(frame_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- *frame_rate = wfd->stream_info.video_stream_info.frame_rate;
-
- return MM_ERROR_NONE;
-}
-
-int mm_wfd_sink_set_resolution(MMHandleType wfd_sink, gint resolution)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
- MMWFDSINK_CMD_LOCK(wfd_sink);
- result = _mm_wfd_sink_set_resolution((mm_wfd_sink_t *)wfd_sink, resolution);
- MMWFDSINK_CMD_UNLOCK(wfd_sink);
-
- return result;
-}
-
-int mm_wfd_sink_get_negotiated_video_codec(MMHandleType wfd_sink, gint *codec)
-{
- int result = MM_ERROR_NONE;
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(codec, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd);
-
- MMWFDSINK_PRINT_STATE(wfd);
- cur_state = MMWFDSINK_CURRENT_STATE(wfd);
- if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
- cur_state != MM_WFD_SINK_STATE_PLAYING &&
- cur_state != MM_WFD_SINK_STATE_PAUSED) {
-
- wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
- result = MM_ERROR_WFD_INVALID_STATE;
- } else {
- *codec = wfd->stream_info.video_stream_info.codec;
- }
-
- MMWFDSINK_CMD_UNLOCK(wfd);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int mm_wfd_sink_get_negotiated_video_resolution(MMHandleType wfd_sink, gint *width, gint *height)
-{
- int result = MM_ERROR_NONE;
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(width, MM_ERROR_WFD_INVALID_ARGUMENT);
- wfd_sink_return_val_if_fail(height, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd);
-
- MMWFDSINK_PRINT_STATE(wfd);
- cur_state = MMWFDSINK_CURRENT_STATE(wfd);
- if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
- cur_state != MM_WFD_SINK_STATE_PLAYING &&
- cur_state != MM_WFD_SINK_STATE_PAUSED) {
-
- wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
- result = MM_ERROR_WFD_INVALID_STATE;
- } else {
- *width = wfd->stream_info.video_stream_info.width;
- *height = wfd->stream_info.video_stream_info.height;
- }
-
- MMWFDSINK_CMD_UNLOCK(wfd);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int mm_wfd_sink_get_negotiated_video_frame_rate(MMHandleType wfd_sink, gint *frame_rate)
-{
- int result = MM_ERROR_NONE;
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(frame_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd);
-
- MMWFDSINK_PRINT_STATE(wfd);
- cur_state = MMWFDSINK_CURRENT_STATE(wfd);
- if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
- cur_state != MM_WFD_SINK_STATE_PLAYING &&
- cur_state != MM_WFD_SINK_STATE_PAUSED) {
-
- wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
- result = MM_ERROR_WFD_INVALID_STATE;
- } else {
- *frame_rate = wfd->stream_info.video_stream_info.frame_rate;
- }
-
- MMWFDSINK_CMD_UNLOCK(wfd);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int mm_wfd_sink_get_negotiated_audio_codec(MMHandleType wfd_sink, gint *codec)
-{
- int result = MM_ERROR_NONE;
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(codec, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd);
-
- MMWFDSINK_PRINT_STATE(wfd);
- cur_state = MMWFDSINK_CURRENT_STATE(wfd);
- if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
- cur_state != MM_WFD_SINK_STATE_PLAYING &&
- cur_state != MM_WFD_SINK_STATE_PAUSED) {
-
- wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
- result = MM_ERROR_WFD_INVALID_STATE;
- } else {
- *codec = wfd->stream_info.audio_stream_info.codec;
- }
-
- MMWFDSINK_CMD_UNLOCK(wfd);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int mm_wfd_sink_get_negotiated_audio_channel(MMHandleType wfd_sink, gint *channel)
-{
- int result = MM_ERROR_NONE;
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(channel, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd);
-
- MMWFDSINK_PRINT_STATE(wfd);
- cur_state = MMWFDSINK_CURRENT_STATE(wfd);
- if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
- cur_state != MM_WFD_SINK_STATE_PLAYING &&
- cur_state != MM_WFD_SINK_STATE_PAUSED) {
-
- wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
- result = MM_ERROR_WFD_INVALID_STATE;
- } else {
- *channel = wfd->stream_info.audio_stream_info.channels;
- }
-
- MMWFDSINK_CMD_UNLOCK(wfd);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int mm_wfd_sink_get_negotiated_audio_sample_rate(MMHandleType wfd_sink, gint *sample_rate)
-{
- int result = MM_ERROR_NONE;
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(sample_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd);
-
- MMWFDSINK_PRINT_STATE(wfd);
- cur_state = MMWFDSINK_CURRENT_STATE(wfd);
- if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
- cur_state != MM_WFD_SINK_STATE_PLAYING &&
- cur_state != MM_WFD_SINK_STATE_PAUSED) {
-
- wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
- result = MM_ERROR_WFD_INVALID_STATE;
- } else {
- *sample_rate = wfd->stream_info.audio_stream_info.sample_rate;
- }
-
- MMWFDSINK_CMD_UNLOCK(wfd);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int mm_wfd_sink_get_negotiated_audio_bitwidth(MMHandleType wfd_sink, gint *bitwidth)
-{
- int result = MM_ERROR_NONE;
- mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(bitwidth, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- MMWFDSINK_CMD_LOCK(wfd);
-
- MMWFDSINK_PRINT_STATE(wfd);
- cur_state = MMWFDSINK_CURRENT_STATE(wfd);
- if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
- cur_state != MM_WFD_SINK_STATE_PLAYING &&
- cur_state != MM_WFD_SINK_STATE_PAUSED) {
-
- wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
- result = MM_ERROR_WFD_INVALID_STATE;
- } else {
- *bitwidth = wfd->stream_info.audio_stream_info.bitwidth;
- }
-
- MMWFDSINK_CMD_UNLOCK(wfd);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
- * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-
-#include "mm_wfd_sink_manager.h"
-
-
-static gpointer __mm_wfd_sink_manager_thread(gpointer data);
-
-int _mm_wfd_sink_init_manager(mm_wfd_sink_t *wfd_sink)
-{
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* create manager mutex */
- g_mutex_init(&(wfd_sink->manager_thread_mutex));
-
- /* create capture cond */
- g_cond_init(&(wfd_sink->manager_thread_cond));
-
- wfd_sink->manager_thread_cmd = NULL;
- wfd_sink->manager_thread_exit = FALSE;
-
- /* create manager thread */
- wfd_sink->manager_thread =
- g_thread_new("__mm_wfd_sink_manager_thread", __mm_wfd_sink_manager_thread, (gpointer)wfd_sink);
- if (wfd_sink->manager_thread == NULL) {
- wfd_sink_error("failed to create manager thread\n");
- goto failed_to_init;
- }
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
-failed_to_init:
- g_mutex_clear(&(wfd_sink->manager_thread_mutex));
- g_cond_clear(&(wfd_sink->manager_thread_cond));
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-int _mm_wfd_sink_release_manager(mm_wfd_sink_t *wfd_sink)
-{
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* release manager thread */
- if (wfd_sink->manager_thread) {
- WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_EXIT);
- WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
-
- wfd_sink_debug("waitting for manager thread exit");
- g_thread_join(wfd_sink->manager_thread);
- g_mutex_clear(&(wfd_sink->manager_thread_mutex));
- g_cond_clear(&(wfd_sink->manager_thread_cond));
- wfd_sink_debug("manager thread released");
- }
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static gpointer
-__mm_wfd_sink_manager_thread(gpointer data)
-{
- mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *) data;
- WFDSinkManagerCMDType cmd = WFD_SINK_MANAGER_CMD_NONE;
- GList *walk = NULL;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, NULL);
-
- if (wfd_sink->manager_thread_exit) {
- wfd_sink_debug("exit manager thread...");
- return NULL;
- }
-
- wfd_sink_debug("manager thread started. waiting for signal");
-
- while (TRUE) {
- WFD_SINK_MANAGER_LOCK(wfd_sink);
- WFD_SINK_MANAGER_WAIT_CMD(wfd_sink);
-
- for (walk = wfd_sink->manager_thread_cmd; walk; walk = g_list_next(walk)) {
- cmd = GPOINTER_TO_INT(walk->data);
-
- wfd_sink_debug("got command %d", cmd);
-
- switch (cmd) {
- case WFD_SINK_MANAGER_CMD_LINK_A_DECODEBIN:
- wfd_sink_debug("try to link audio decodebin.");
- if (MM_ERROR_NONE != __mm_wfd_sink_link_audio_decodebin(wfd_sink)) {
- wfd_sink_error("failed to link audio decodebin.....\n");
- goto EXIT;
- }
- break;
- case WFD_SINK_MANAGER_CMD_LINK_V_DECODEBIN:
- wfd_sink_debug("try to link video decodebin.");
- if (MM_ERROR_NONE != __mm_wfd_sink_link_video_decodebin(wfd_sink)) {
- wfd_sink_error("failed to link video decodebin.....\n");
- goto EXIT;
- }
- break;
- case WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE:
- wfd_sink_debug("try to prepare audio pipeline.");
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink)) {
- wfd_sink_error("failed to prepare audio pipeline.....\n");
- goto EXIT;
- }
- break;
- case WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE:
- wfd_sink_debug("try to prepare video pipeline.");
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink)) {
- wfd_sink_error("failed to prepare video pipeline.....\n");
- goto EXIT;
- }
- break;
- case WFD_SINK_MANAGER_CMD_EXIT:
- wfd_sink_debug("exiting manager thread");
- goto EXIT;
- break;
- default:
- break;
- }
- }
-
- g_list_free(wfd_sink->manager_thread_cmd);
- wfd_sink->manager_thread_cmd = NULL;
-
- WFD_SINK_MANAGER_UNLOCK(wfd_sink);
- }
-
- wfd_sink_debug_fleave();
-
- return NULL;
-
-EXIT:
- wfd_sink->manager_thread_exit = TRUE;
- g_list_free(wfd_sink->manager_thread_cmd);
- wfd_sink->manager_thread_cmd = NULL;
- WFD_SINK_MANAGER_UNLOCK(wfd_sink);
-
- return NULL;
-}
-
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <gst/gst.h>
-#include <gst/video/videooverlay.h>
-#include <Elementary.h>
-#include <Ecore_Wayland.h>
-
-#include "mm_wfd_sink_util.h"
-#include "mm_wfd_sink_priv.h"
-#include "mm_wfd_sink_manager.h"
-#include "mm_wfd_sink_dlog.h"
-#include "mm_wfd_sink_wfd_enum.h"
-#include "mm_wfd_sink_wayland.h"
-
-
-/* gstreamer */
-static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink);
-static int __mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboolean async);
-
-/* state */
-static int __mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd);
-static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType state);
-
-/* util */
-static void __mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink);
-static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint *CEA_resolution, guint *VESA_resolution, guint *HH_resolution);
-
-int _mm_wfd_sink_create(mm_wfd_sink_t **wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- mm_wfd_sink_t *new_wfd_sink = NULL;
-
- /* create handle */
- new_wfd_sink = g_malloc0(sizeof(mm_wfd_sink_t));
- if (!new_wfd_sink) {
- wfd_sink_error("failed to allocate memory for wi-fi display sink");
- return MM_ERROR_WFD_NO_FREE_SPACE;
- }
-
- /* Initialize gstreamer related */
- new_wfd_sink->attrs = 0;
-
- new_wfd_sink->pipeline = NULL;
- new_wfd_sink->audio_decodebin_is_linked = FALSE;
- new_wfd_sink->video_decodebin_is_linked = FALSE;
-
- /* Initialize timestamp compensation related */
- new_wfd_sink->need_to_reset_basetime = FALSE;
- new_wfd_sink->clock = NULL;
- new_wfd_sink->video_buffer_count = 0LL;
- new_wfd_sink->video_average_gap = 0LL;
- new_wfd_sink->video_accumulated_gap = 0LL;
- new_wfd_sink->audio_buffer_count = 0LL;
- new_wfd_sink->audio_average_gap = 0LL;
- new_wfd_sink->audio_accumulated_gap = 0LL;
- new_wfd_sink->last_buffer_timestamp = GST_CLOCK_TIME_NONE;
-
- /* Initialize all states */
- MMWFDSINK_CURRENT_STATE(new_wfd_sink) = MM_WFD_SINK_STATE_NONE;
- MMWFDSINK_PREVIOUS_STATE(new_wfd_sink) = MM_WFD_SINK_STATE_NONE;
- MMWFDSINK_PENDING_STATE(new_wfd_sink) = MM_WFD_SINK_STATE_NONE;
-
- /* initialize audio/video information */
- new_wfd_sink->stream_info.audio_stream_info.codec = MM_WFD_SINK_AUDIO_CODEC_NONE;
- new_wfd_sink->stream_info.audio_stream_info.channels = 0;
- new_wfd_sink->stream_info.audio_stream_info.sample_rate = 0;
- new_wfd_sink->stream_info.audio_stream_info.bitwidth = 0;
- new_wfd_sink->stream_info.video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_NONE;
- new_wfd_sink->stream_info.video_stream_info.width = 0;
- new_wfd_sink->stream_info.video_stream_info.height = 0;
- new_wfd_sink->stream_info.video_stream_info.frame_rate = 0;
-
- /* Initialize command */
- new_wfd_sink->cmd = MM_WFD_SINK_COMMAND_CREATE;
- new_wfd_sink->waiting_cmd = FALSE;
-
- /* Initialize manager related */
- new_wfd_sink->manager_thread = NULL;
- new_wfd_sink->manager_thread_cmd = NULL;
- new_wfd_sink->manager_thread_exit = FALSE;
-
- /* Initialize video resolution */
- new_wfd_sink->supportive_resolution = MM_WFD_SINK_RESOLUTION_UNKNOWN;
-
- /* construct attributes */
- new_wfd_sink->attrs = _mmwfd_construct_attribute((MMHandleType)new_wfd_sink);
- if (!new_wfd_sink->attrs) {
- MMWFDSINK_FREEIF(new_wfd_sink);
- wfd_sink_error("failed to set attribute");
- return MM_ERROR_WFD_INTERNAL;
- }
-
- /* load ini for initialize */
- result = mm_wfd_sink_ini_load(&new_wfd_sink->ini);
- if (result != MM_ERROR_NONE) {
- wfd_sink_error("failed to load ini file");
- goto fail_to_load_ini;
- }
- new_wfd_sink->need_to_reset_basetime = new_wfd_sink->ini.enable_reset_basetime;
-
- /* initialize manager */
- result = _mm_wfd_sink_init_manager(new_wfd_sink);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("failed to init manager : %d", result);
- goto fail_to_init;
- }
-
- /* initialize gstreamer */
- result = __mm_wfd_sink_init_gstreamer(new_wfd_sink);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("failed to init gstreamer : %d", result);
- goto fail_to_init;
- }
-
- /* set state */
- __mm_wfd_sink_set_state(new_wfd_sink, MM_WFD_SINK_STATE_NULL);
-
- /* now take handle */
- *wfd_sink = new_wfd_sink;
-
- wfd_sink_debug_fleave();
-
- return result;
-
- /* ERRORS */
-fail_to_init:
- mm_wfd_sink_ini_unload(&new_wfd_sink->ini);
-fail_to_load_ini:
- _mmwfd_deconstruct_attribute(new_wfd_sink->attrs);
- MMWFDSINK_FREEIF(new_wfd_sink);
-
- *wfd_sink = NULL;
-
- return result;
-}
-
-int _mm_wfd_sink_prepare(mm_wfd_sink_t *wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check current wi-fi display sink state */
- MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_PREPARE);
-
- /* construct pipeline */
- /* create main pipeline */
- result = __mm_wfd_sink_create_pipeline(wfd_sink);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("failed to create pipeline : %d", result);
- goto fail_to_create;
- }
-
- /* create video decodebin */
- result = __mm_wfd_sink_create_video_decodebin(wfd_sink);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("failed to create video decodebin %d", result);
- goto fail_to_create;
- }
-
- /* create video sinkbin */
- result = __mm_wfd_sink_create_video_sinkbin(wfd_sink);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("failed to create video sinkbin %d", result);
- goto fail_to_create;
- }
-
- /* create audio decodebin */
- result = __mm_wfd_sink_create_audio_decodebin(wfd_sink);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("fail to create audio decodebin : %d", result);
- goto fail_to_create;
- }
-
- /* create audio sinkbin */
- result = __mm_wfd_sink_create_audio_sinkbin(wfd_sink);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("fail to create audio sinkbin : %d", result);
- goto fail_to_create;
- }
-
- /* set pipeline READY state */
- result = __mm_wfd_sink_set_pipeline_state(wfd_sink, GST_STATE_READY, TRUE);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("failed to set state : %d", result);
- goto fail_to_create;
- }
-
- /* set state */
- __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_PREPARED);
-
- wfd_sink_debug_fleave();
-
- return result;
-
- /* ERRORS */
-fail_to_create:
- /* need to destroy pipeline already created */
- __mm_wfd_sink_destroy_pipeline(wfd_sink);
- return result;
-}
-
-int _mm_wfd_sink_connect(mm_wfd_sink_t *wfd_sink, const char *uri)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(uri && strlen(uri) > strlen("rtsp://"), MM_ERROR_WFD_INVALID_ARGUMENT);
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_DEPAY].gst &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_DEMUX].gst,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check current wi-fi display sink state */
- MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_CONNECT);
-
- wfd_sink_debug("try to connect to %s.....", GST_STR_NULL(uri));
-
- /* set uri to wfdsrc */
- g_object_set(G_OBJECT(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst), "location", uri, NULL);
-
- /* set pipeline PAUSED state */
- result = __mm_wfd_sink_set_pipeline_state(wfd_sink, GST_STATE_PAUSED, TRUE);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("failed to set state : %d", result);
- return result;
- }
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int _mm_wfd_sink_start(mm_wfd_sink_t *wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check current wi-fi display sink state */
- MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_START);
-
- WFD_SINK_MANAGER_LOCK(wfd_sink) ;
- wfd_sink_debug("check pipeline is ready to start");
- WFD_SINK_MANAGER_UNLOCK(wfd_sink);
-
- result = __mm_wfd_sink_set_pipeline_state(wfd_sink, GST_STATE_PLAYING, TRUE);
- if (result < MM_ERROR_NONE) {
- wfd_sink_error("failed to set state : %d", result);
- return result;
- }
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int _mm_wfd_sink_pause(mm_wfd_sink_t *wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check current wi-fi display sink state */
- MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_PAUSE);
-
- g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "pause", NULL);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int _mm_wfd_sink_resume(mm_wfd_sink_t *wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check current wi-fi display sink state */
- MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_RESUME);
-
- g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "resume", NULL);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int _mm_wfd_sink_disconnect(mm_wfd_sink_t *wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check current wi-fi display sink state */
- MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_DISCONNECT);
-
- WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_EXIT);
- WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
-
- g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "close", NULL);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int _mm_wfd_sink_unprepare(mm_wfd_sink_t *wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check current wi-fi display sink state */
- MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_UNPREPARE);
-
- WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_EXIT);
- WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
-
- /* release pipeline */
- result = __mm_wfd_sink_destroy_pipeline(wfd_sink);
- if (result != MM_ERROR_NONE) {
- wfd_sink_error("failed to destory pipeline");
- return MM_ERROR_WFD_INTERNAL;
- } else {
- wfd_sink_debug("success to destory pipeline");
- }
-
- /* set state */
- __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_NULL);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int _mm_wfd_sink_destroy(mm_wfd_sink_t *wfd_sink)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check current wi-fi display sink state */
- MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_DESTROY);
-
- /* unload ini */
- mm_wfd_sink_ini_unload(&wfd_sink->ini);
-
- /* release attributes */
- _mmwfd_deconstruct_attribute(wfd_sink->attrs);
-
- if (MM_ERROR_NONE != _mm_wfd_sink_release_manager(wfd_sink)) {
- wfd_sink_error("failed to release manager");
- return MM_ERROR_WFD_INTERNAL;
- }
-
-
- /* set state */
- __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_NONE);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-int _mm_wfd_set_message_callback(mm_wfd_sink_t *wfd_sink, MMWFDMessageCallback callback, void *user_data)
-{
- int result = MM_ERROR_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- wfd_sink->msg_cb = callback;
- wfd_sink->msg_user_data = user_data;
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink)
-{
- int result = MM_ERROR_NONE;
- gint *argc = NULL;
- gchar **argv = NULL;
- static const int max_argc = 50;
- GError *err = NULL;
- gint i = 0;
-
- wfd_sink_debug_fenter();
-
- /* alloc */
- argc = calloc(1, sizeof(gint));
- argv = calloc(max_argc, sizeof(gchar *));
- if (!argc || !argv) {
- wfd_sink_error("failed to allocate memory for wfdsink");
-
- MMWFDSINK_FREEIF(argv);
- MMWFDSINK_FREEIF(argc);
-
- return MM_ERROR_WFD_NO_FREE_SPACE;
- }
-
- /* we would not do fork for scanning plugins */
- argv[*argc] = g_strdup("--gst-disable-registry-fork");
- (*argc)++;
-
- /* check disable registry scan */
- argv[*argc] = g_strdup("--gst-disable-registry-update");
- (*argc)++;
-
- /* check disable segtrap */
- argv[*argc] = g_strdup("--gst-disable-segtrap");
- (*argc)++;
-
- /* check ini */
- for (i = 0; i < 5; i++) {
- if (strlen(wfd_sink->ini.gst_param[i]) > 2) {
- wfd_sink_debug("set %s", wfd_sink->ini.gst_param[i]);
- argv[*argc] = g_strdup(wfd_sink->ini.gst_param[i]);
- (*argc)++;
- }
- }
-
- wfd_sink_debug("initializing gstreamer with following parameter");
- wfd_sink_debug("argc : %d", *argc);
-
- for (i = 0; i < *argc; i++) {
- wfd_sink_debug("argv[%d] : %s", i, argv[i]);
- }
-
- /* initializing gstreamer */
- if (!gst_init_check(argc, &argv, &err)) {
- wfd_sink_error("failed to initialize gstreamer: %s", err ? err->message : "unknown error occurred");
- if (err)
- g_error_free(err);
-
- result = MM_ERROR_WFD_INTERNAL;
- }
-
- /* release */
- for (i = 0; i < *argc; i++) {
- MMWFDSINK_FREEIF(argv[i]);
- }
- MMWFDSINK_FREEIF(argv);
- MMWFDSINK_FREEIF(argc);
-
- wfd_sink_debug_fleave();
-
- return result;
-}
-
-static GstBusSyncReply
-_mm_wfd_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data)
-{
- GstBusSyncReply ret = GST_BUS_PASS;
-
- wfd_sink_return_val_if_fail(message &&
- GST_IS_MESSAGE(message) &&
- GST_MESSAGE_SRC(message),
- GST_BUS_DROP);
-
- switch (GST_MESSAGE_TYPE(message)) {
- case GST_MESSAGE_TAG:
- break;
- case GST_MESSAGE_DURATION:
- break;
- case GST_MESSAGE_STATE_CHANGED: {
- /* we only handle state change messages from pipeline */
- if (!GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
- ret = GST_BUS_DROP;
- }
- break;
- case GST_MESSAGE_ASYNC_DONE: {
- if (!GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
- ret = GST_BUS_DROP;
- }
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static gboolean
-_mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
-{
- mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *) data;
- const GstStructure *message_structure = gst_message_get_structure(msg);
- gboolean ret = TRUE;
-
- wfd_sink_return_val_if_fail(wfd_sink, FALSE);
- wfd_sink_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE);
-
- wfd_sink_debug("got %s from %s",
- GST_STR_NULL(GST_MESSAGE_TYPE_NAME(msg)),
- GST_STR_NULL(GST_OBJECT_NAME(GST_MESSAGE_SRC(msg))));
-
- switch (GST_MESSAGE_TYPE(msg)) {
- case GST_MESSAGE_ERROR: {
- GError *error = NULL;
- gchar *debug = NULL;
-
- /* get error code */
- gst_message_parse_error(msg, &error, &debug);
-
- wfd_sink_error("error : %s", error->message);
- wfd_sink_error("debug : %s", debug);
-
- MMWFDSINK_FREEIF(debug);
- g_error_free(error);
- }
- break;
-
- case GST_MESSAGE_WARNING: {
- char *debug = NULL;
- GError *error = NULL;
-
- gst_message_parse_warning(msg, &error, &debug);
-
- wfd_sink_warning("warning : %s", error->message);
- wfd_sink_warning("debug : %s", debug);
-
- MMWFDSINK_FREEIF(debug);
- g_error_free(error);
- }
- break;
-
- case GST_MESSAGE_STATE_CHANGED: {
- const GValue *voldstate, *vnewstate, *vpending;
- GstState oldstate, newstate, pending;
- const GstStructure *structure;
-
- /* we only handle messages from pipeline */
- if (msg->src != (GstObject *)wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst)
- break;
-
- /* get state info from msg */
- structure = gst_message_get_structure(msg);
- if (structure == NULL)
- break;
-
- voldstate = gst_structure_get_value(structure, "old-state");
- vnewstate = gst_structure_get_value(structure, "new-state");
- vpending = gst_structure_get_value(structure, "pending-state");
- if (voldstate == NULL || vnewstate == NULL || vpending == NULL)
- break;
-
- oldstate = (GstState)voldstate->data[0].v_int;
- newstate = (GstState)vnewstate->data[0].v_int;
- pending = (GstState)vpending->data[0].v_int;
-
- wfd_sink_debug("state changed [%s] : %s--->%s final : %s",
- GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
- gst_element_state_get_name((GstState)oldstate),
- gst_element_state_get_name((GstState)newstate),
- gst_element_state_get_name((GstState)pending));
-
- if (oldstate == newstate) {
- wfd_sink_debug("pipeline reports state transition to old state");
- break;
- }
-
- switch (newstate) {
- case GST_STATE_VOID_PENDING:
- case GST_STATE_NULL:
- case GST_STATE_READY:
- case GST_STATE_PAUSED:
- case GST_STATE_PLAYING:
- default:
- break;
- }
- }
- break;
-
- case GST_MESSAGE_CLOCK_LOST: {
- GstClock *clock = NULL;
- gst_message_parse_clock_lost(msg, &clock);
- wfd_sink_debug("The current clock[%s] as selected by the pipeline became unusable.", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
- }
- break;
-
- case GST_MESSAGE_NEW_CLOCK: {
- GstClock *clock = NULL;
- gst_message_parse_new_clock(msg, &clock);
- if (!clock)
- break;
-
- if (wfd_sink->clock) {
- if (wfd_sink->clock != clock)
- wfd_sink_debug("clock is changed! [%s] -->[%s]",
- GST_STR_NULL(GST_OBJECT_NAME(wfd_sink->clock)),
- GST_STR_NULL(GST_OBJECT_NAME(clock)));
- else
- wfd_sink_debug("same clock is selected again! [%s]",
- GST_STR_NULL(GST_OBJECT_NAME(clock)));
- } else {
- wfd_sink_debug("new clock [%s] was selected in the pipeline",
- (GST_STR_NULL(GST_OBJECT_NAME(clock))));
- }
-
- wfd_sink->clock = clock;
- }
- break;
-
- case GST_MESSAGE_APPLICATION: {
- const gchar *message_structure_name;
-
- message_structure_name = gst_structure_get_name(message_structure);
- if (!message_structure_name)
- break;
-
- wfd_sink_debug("message name : %s", GST_STR_NULL(message_structure_name));
- }
- break;
-
- case GST_MESSAGE_ELEMENT: {
- const gchar *structure_name = NULL;
-
- structure_name = gst_structure_get_name(message_structure);
- if (structure_name) {
- wfd_sink_debug("got element specific message[%s]", GST_STR_NULL(structure_name));
- if (g_strrstr(structure_name, "GstUDPSrcTimeout")) {
- wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
- } else if (g_strrstr(structure_name, "GstWFDSrcSessionTimeout")) {
- wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
- }
- }
- }
- break;
-
- case GST_MESSAGE_PROGRESS: {
- GstProgressType type = GST_PROGRESS_TYPE_ERROR;
- gchar *category = NULL, *text = NULL;
-
- gst_message_parse_progress(msg, &type, &category, &text);
- wfd_sink_debug("%s : %s ", GST_STR_NULL(category), GST_STR_NULL(text));
-
- switch (type) {
- case GST_PROGRESS_TYPE_START:
- break;
- case GST_PROGRESS_TYPE_COMPLETE:
- if (category && !strcmp(category, "open"))
- __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_CONNECTED);
- else if (category && !strcmp(category, "play")) {
- __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_PLAYING);
- /*_mm_wfd_sink_correct_pipeline_latency (wfd_sink); */
- } else if (category && !strcmp(category, "pause"))
- __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_PAUSED);
- else if (category && !strcmp(category, "close"))
- __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_DISCONNECTED);
- break;
- case GST_PROGRESS_TYPE_CANCELED:
- break;
- case GST_PROGRESS_TYPE_ERROR:
- if (category && !strcmp(category, "open")) {
- wfd_sink_error("got error : %s", GST_STR_NULL(text));
- /*_mm_wfd_sink_disconnect (wfd_sink); */
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
- } else if (category && !strcmp(category, "play")) {
- wfd_sink_error("got error : %s", GST_STR_NULL(text));
- /*_mm_wfd_sink_disconnect (wfd_sink); */
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
- } else if (category && !strcmp(category, "pause")) {
- wfd_sink_error("got error : %s", GST_STR_NULL(text));
- /*_mm_wfd_sink_disconnect (wfd_sink); */
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
- } else if (category && !strcmp(category, "close")) {
- wfd_sink_error("got error : %s", GST_STR_NULL(text));
- /*_mm_wfd_sink_disconnect (wfd_sink); */
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
- } else {
- wfd_sink_error("got error : %s", GST_STR_NULL(text));
- }
- break;
- default:
- wfd_sink_error("progress message has no type");
- return ret;
- }
-
- MMWFDSINK_FREEIF(category);
- MMWFDSINK_FREEIF(text);
- }
- break;
- case GST_MESSAGE_ASYNC_START:
- wfd_sink_debug("GST_MESSAGE_ASYNC_START : %s", gst_element_get_name(GST_MESSAGE_SRC(msg)));
- break;
- case GST_MESSAGE_ASYNC_DONE:
- wfd_sink_debug("GST_MESSAGE_ASYNC_DONE : %s", gst_element_get_name(GST_MESSAGE_SRC(msg)));
- break;
- case GST_MESSAGE_UNKNOWN:
- case GST_MESSAGE_INFO:
- case GST_MESSAGE_TAG:
- case GST_MESSAGE_BUFFERING:
- case GST_MESSAGE_EOS:
- case GST_MESSAGE_STATE_DIRTY:
- case GST_MESSAGE_STEP_DONE:
- case GST_MESSAGE_CLOCK_PROVIDE:
- case GST_MESSAGE_STRUCTURE_CHANGE:
- case GST_MESSAGE_STREAM_STATUS:
- case GST_MESSAGE_SEGMENT_START:
- case GST_MESSAGE_SEGMENT_DONE:
- case GST_MESSAGE_DURATION:
- case GST_MESSAGE_LATENCY:
- case GST_MESSAGE_REQUEST_STATE:
- case GST_MESSAGE_STEP_START:
- case GST_MESSAGE_QOS:
- case GST_MESSAGE_ANY:
- break;
- default:
- wfd_sink_debug("unhandled message");
- break;
- }
-
- return ret;
-}
-
-static int
-__mm_wfd_sink_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket, gboolean need_prepare)
-{
- GList *bucket = element_bucket;
- MMWFDSinkGstElement *element = NULL;
- int successful_add_count = 0;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(element_bucket, 0);
- wfd_sink_return_val_if_fail(bin, 0);
-
- for (; bucket; bucket = bucket->next) {
- element = (MMWFDSinkGstElement *)bucket->data;
-
- if (element && element->gst) {
- if (need_prepare)
- gst_element_set_state(GST_ELEMENT(element->gst), GST_STATE_READY);
-
- if (!gst_bin_add(GST_BIN(bin), GST_ELEMENT(element->gst))) {
- wfd_sink_error("failed to add element [%s] to bin [%s]",
- GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
- GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
- return 0;
- }
-
- wfd_sink_debug("add element [%s] to bin [%s]",
- GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
- GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
-
- successful_add_count++;
- }
- }
-
- wfd_sink_debug_fleave();
-
- return successful_add_count;
-}
-
-static int
-__mm_wfd_sink_gst_element_link_bucket(GList *element_bucket)
-{
- GList *bucket = element_bucket;
- MMWFDSinkGstElement *element = NULL;
- MMWFDSinkGstElement *prv_element = NULL;
- gint successful_link_count = 0;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(element_bucket, -1);
-
- prv_element = (MMWFDSinkGstElement *)bucket->data;
- bucket = bucket->next;
-
- for (; bucket; bucket = bucket->next) {
- element = (MMWFDSinkGstElement *)bucket->data;
-
- if (element && element->gst) {
- if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
- wfd_sink_debug("linking [%s] to [%s] success",
- GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
- GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
- successful_link_count++;
- } else {
- wfd_sink_error("linking [%s] to [%s] failed",
- GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
- GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
- return -1;
- }
- }
-
- prv_element = element;
- }
-
- wfd_sink_debug_fleave();
-
- return successful_link_count;
-}
-
-static int
-__mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd)
-{
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_PRINT_STATE(wfd_sink);
-
- cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
-
- switch (cmd) {
- case MM_WFD_SINK_COMMAND_CREATE: {
- if (cur_state != MM_WFD_SINK_STATE_NONE)
- goto invalid_state;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NULL;
- }
- break;
-
- case MM_WFD_SINK_COMMAND_PREPARE: {
- if (cur_state == MM_WFD_SINK_STATE_PREPARED)
- goto no_operation;
- else if (cur_state != MM_WFD_SINK_STATE_NULL)
- goto invalid_state;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PREPARED;
- }
- break;
-
- case MM_WFD_SINK_COMMAND_CONNECT: {
- if (cur_state == MM_WFD_SINK_STATE_CONNECTED)
- goto no_operation;
- else if (cur_state != MM_WFD_SINK_STATE_PREPARED)
- goto invalid_state;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_CONNECTED;
- }
- break;
-
- case MM_WFD_SINK_COMMAND_START: {
- if (cur_state == MM_WFD_SINK_STATE_PLAYING)
- goto no_operation;
- else if (cur_state != MM_WFD_SINK_STATE_CONNECTED)
- goto invalid_state;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PLAYING;
- }
- break;
-
- case MM_WFD_SINK_COMMAND_PAUSE: {
- if (cur_state == MM_WFD_SINK_STATE_PAUSED)
- goto no_operation;
- else if (cur_state != MM_WFD_SINK_STATE_PLAYING)
- goto invalid_state;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PAUSED;
- }
- break;
-
- case MM_WFD_SINK_COMMAND_RESUME: {
- if (cur_state == MM_WFD_SINK_STATE_PLAYING)
- goto no_operation;
- else if (cur_state != MM_WFD_SINK_STATE_PAUSED)
- goto invalid_state;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PLAYING;
- }
- break;
-
- case MM_WFD_SINK_COMMAND_DISCONNECT: {
- if (cur_state == MM_WFD_SINK_STATE_NONE ||
- cur_state == MM_WFD_SINK_STATE_NULL ||
- cur_state == MM_WFD_SINK_STATE_PREPARED ||
- cur_state == MM_WFD_SINK_STATE_DISCONNECTED)
- goto no_operation;
- else if (cur_state != MM_WFD_SINK_STATE_PLAYING &&
- cur_state != MM_WFD_SINK_STATE_CONNECTED &&
- cur_state != MM_WFD_SINK_STATE_PAUSED)
- goto invalid_state;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_DISCONNECTED;
- }
- break;
-
- case MM_WFD_SINK_COMMAND_UNPREPARE: {
- if (cur_state == MM_WFD_SINK_STATE_NONE ||
- cur_state == MM_WFD_SINK_STATE_NULL)
- goto no_operation;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NULL;
- }
- break;
-
- case MM_WFD_SINK_COMMAND_DESTROY: {
- if (cur_state == MM_WFD_SINK_STATE_NONE)
- goto no_operation;
-
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
- }
- break;
-
- default:
- break;
- }
-
- wfd_sink->cmd = cmd;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
-no_operation:
- wfd_sink_debug("already %s state, nothing to do.", MMWFDSINK_STATE_GET_NAME(cur_state));
- return MM_ERROR_WFD_NO_OP;
-
- /* ERRORS */
-invalid_state:
- wfd_sink_error("current state is invalid.", MMWFDSINK_STATE_GET_NAME(cur_state));
- return MM_ERROR_WFD_INVALID_STATE;
-}
-
-static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType state)
-{
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- if (MMWFDSINK_CURRENT_STATE(wfd_sink) == state) {
- wfd_sink_error("already state(%s)", MMWFDSINK_STATE_GET_NAME(state));
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
- return MM_ERROR_NONE;
- }
-
- /* update wi-fi display state */
- MMWFDSINK_PREVIOUS_STATE(wfd_sink) = MMWFDSINK_CURRENT_STATE(wfd_sink);
- MMWFDSINK_CURRENT_STATE(wfd_sink) = state;
-
- if (MMWFDSINK_CURRENT_STATE(wfd_sink) == MMWFDSINK_PENDING_STATE(wfd_sink))
- MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
-
- /* poset state message to application */
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_NONE,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
-
- /* print state */
- MMWFDSINK_PRINT_STATE(wfd_sink);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int
-__mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboolean async)
-{
- GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
- GstState cur_state = GST_STATE_VOID_PENDING;
- GstState pending_state = GST_STATE_VOID_PENDING;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- wfd_sink_return_val_if_fail(state > GST_STATE_VOID_PENDING, MM_ERROR_WFD_INVALID_ARGUMENT);
-
- wfd_sink_debug("try to set %s state ", gst_element_state_get_name(state));
-
- result = gst_element_set_state(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst, state);
- if (result == GST_STATE_CHANGE_FAILURE) {
- wfd_sink_error("fail to set %s state....", gst_element_state_get_name(state));
- return MM_ERROR_WFD_INTERNAL;
- }
-
- if (!async) {
- wfd_sink_debug("wait for changing state is completed ");
-
- result = gst_element_get_state(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst, &cur_state, &pending_state, wfd_sink->ini.state_change_timeout * GST_SECOND);
- if (result == GST_STATE_CHANGE_FAILURE) {
- wfd_sink_error("fail to get state within %d seconds....", wfd_sink->ini.state_change_timeout);
-
- __mm_wfd_sink_dump_pipeline_state(wfd_sink);
-
- return MM_ERROR_WFD_INTERNAL;
- } else if (result == GST_STATE_CHANGE_NO_PREROLL) {
- wfd_sink_debug("successfully changed state but is not able to provide data yet");
- }
-
- wfd_sink_debug("cur state is %s, pending state is %s",
- gst_element_state_get_name(cur_state),
- gst_element_state_get_name(pending_state));
- }
-
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static void
-_mm_wfd_sink_reset_basetime(mm_wfd_sink_t *wfd_sink)
-{
- GstClockTime base_time = GST_CLOCK_TIME_NONE;
- int i;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
- wfd_sink_return_if_fail(wfd_sink->need_to_reset_basetime);
-
-
- if (wfd_sink->clock)
- base_time = gst_clock_get_time(wfd_sink->clock);
-
- if (GST_CLOCK_TIME_IS_VALID(base_time)) {
-
- wfd_sink_debug("set pipeline base_time as now [%"GST_TIME_FORMAT"]", GST_TIME_ARGS(base_time));
-
- for (i = 0; i < WFD_SINK_M_NUM; i++) {
- if (wfd_sink->pipeline->mainbin[i].gst)
- gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->mainbin[i].gst), base_time);
- }
-
- if (wfd_sink->pipeline->v_decodebin) {
- for (i = 0; i < WFD_SINK_V_D_NUM; i++) {
- if (wfd_sink->pipeline->v_decodebin[i].gst)
- gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->v_decodebin[i].gst), base_time);
- }
- }
-
- if (wfd_sink->pipeline->v_sinkbin) {
- for (i = 0; i < WFD_SINK_V_S_NUM; i++) {
- if (wfd_sink->pipeline->v_sinkbin[i].gst)
- gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->v_sinkbin[i].gst), base_time);
- }
- }
-
- if (wfd_sink->pipeline->a_decodebin) {
- for (i = 0; i < WFD_SINK_A_D_NUM; i++) {
- if (wfd_sink->pipeline->a_decodebin[i].gst)
- gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->a_decodebin[i].gst), base_time);
- }
- }
-
- if (wfd_sink->pipeline->a_sinkbin) {
- for (i = 0; i < WFD_SINK_A_S_NUM; i++) {
- if (wfd_sink->pipeline->a_sinkbin[i].gst)
- gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->a_sinkbin[i].gst), base_time);
- }
- }
-
- wfd_sink->need_to_reset_basetime = FALSE;
- }
-
- wfd_sink_debug_fleave();
-
- return;
-}
-
-int
-__mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
-{
- GstElement *bin = NULL;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check video decodebin is linked */
- if (!wfd_sink->video_decodebin_is_linked) {
- /* check video decodebin is created */
- if (wfd_sink->pipeline->v_decodebin == NULL) {
- if (MM_ERROR_NONE != __mm_wfd_sink_create_video_decodebin(wfd_sink)) {
- wfd_sink_error("failed to create video decodebin....");
- goto ERROR;
- }
- }
-
- if (MM_ERROR_NONE != __mm_wfd_sink_link_video_decodebin(wfd_sink)) {
- wfd_sink_error("failed to link video decodebin.....");
- goto ERROR;
- }
- }
-
- /* check video sinkbin is created */
- if (wfd_sink->pipeline->v_sinkbin == NULL) {
- if (MM_ERROR_NONE != __mm_wfd_sink_create_video_sinkbin(wfd_sink)) {
- wfd_sink_error("failed to create video sinkbin....");
- goto ERROR;
- }
- }
-
- /* set video decodebin state as READY */
- if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
- bin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
- if (GST_STATE(bin) <= GST_STATE_NULL) {
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
- wfd_sink_error("failed to set state(READY) to video decodebin");
- goto ERROR;
- }
- }
- } else {
- wfd_sink_warning("going on without video decodebin....");
- }
-
- /* set video sinkbin state as READY */
- if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
- bin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
- if (GST_STATE(bin) <= GST_STATE_NULL) {
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
- wfd_sink_error("failed to set state(READY) to video sinkbin");
- goto ERROR;
- }
- }
- } else {
- wfd_sink_warning("going on without video sinkbin....");
- }
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
- /* ERRORS */
-ERROR:
- /* need to notify to app */
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink)
-{
- GstElement *bin = NULL;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check audio decodebin is linked */
- if (!wfd_sink->audio_decodebin_is_linked) {
- /* check audio decodebin is created */
- if (wfd_sink->pipeline->a_decodebin == NULL) {
- if (MM_ERROR_NONE != __mm_wfd_sink_create_audio_decodebin(wfd_sink)) {
- wfd_sink_error("failed to create audio decodebin....");
- goto ERROR;
- }
- }
-
- if (MM_ERROR_NONE != __mm_wfd_sink_link_audio_decodebin(wfd_sink)) {
- wfd_sink_error("failed to link audio decodebin.....");
- goto ERROR;
- }
- }
-
- /* check audio sinkbin is created */
- if (wfd_sink->pipeline->a_sinkbin == NULL) {
- if (MM_ERROR_NONE != __mm_wfd_sink_create_audio_sinkbin(wfd_sink)) {
- wfd_sink_error("failed to create audio sinkbin....");
- goto ERROR;
- }
- }
-
- /* set audio decodebin state as READY */
- if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
- bin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
- if (GST_STATE(bin) <= GST_STATE_NULL) {
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
- wfd_sink_error("failed to set state(READY) to audio decodebin");
- goto ERROR;
- }
- }
- } else {
- wfd_sink_warning("going on without audio decodebin....");
- }
-
- /* set audio sinkbin state as READY */
- if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
- bin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
- if (GST_STATE(bin) <= GST_STATE_NULL) {
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin , GST_STATE_READY)) {
- wfd_sink_error("failed to set state(READY) to audio sinkbin");
- goto ERROR;
- }
- }
- } else {
- wfd_sink_warning("going on without audio sinkbin....");
- }
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
- /* ERRORS */
-ERROR:
- /* need to notify to app */
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-#define COMPENSATION_CRETERIA_VALUE 1000000 /* 1 msec */
-#define COMPENSATION_CHECK_PERIOD (30*GST_SECOND) /* 30 sec */
-
-static GstPadProbeReturn
-_mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
-{
- mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)u_data;
- GstClockTime current_time = GST_CLOCK_TIME_NONE;
- GstClockTime start_time = GST_CLOCK_TIME_NONE;
- GstClockTime running_time = GST_CLOCK_TIME_NONE;
- GstClockTime base_time = GST_CLOCK_TIME_NONE;
- GstClockTime render_time = GST_CLOCK_TIME_NONE;
- GstClockTimeDiff diff = GST_CLOCK_TIME_NONE;
- GstBuffer *buffer = NULL;
- gint64 ts_offset = 0LL;
-
- wfd_sink_return_val_if_fail(info, FALSE);
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
- GST_PAD_PROBE_DROP);
-
- if (!wfd_sink->clock) {
- wfd_sink_warning("pipeline did not select clock, yet");
- return GST_PAD_PROBE_OK;
- }
-
- if (wfd_sink->need_to_reset_basetime)
- _mm_wfd_sink_reset_basetime(wfd_sink);
-
- /* calculate current runninig time */
- current_time = gst_clock_get_time(wfd_sink->clock);
- if (g_strrstr(GST_OBJECT_NAME(pad), "video"))
- base_time = gst_element_get_base_time(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst);
- else if (g_strrstr(GST_OBJECT_NAME(pad), "audio"))
- base_time = gst_element_get_base_time(wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst);
- start_time = gst_element_get_start_time(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
- if (GST_CLOCK_TIME_IS_VALID(current_time) &&
- GST_CLOCK_TIME_IS_VALID(start_time) &&
- GST_CLOCK_TIME_IS_VALID(base_time)) {
- running_time = current_time - (start_time + base_time);
- } else {
- wfd_sink_debug("current time %"GST_TIME_FORMAT", start time %"GST_TIME_FORMAT
- " base time %"GST_TIME_FORMAT"", GST_TIME_ARGS(current_time),
- GST_TIME_ARGS(start_time), GST_TIME_ARGS(base_time));
- return GST_PAD_PROBE_OK;
- }
-
- /* calculate this buffer rendering time */
- buffer = gst_pad_probe_info_get_buffer(info);
- if (!GST_BUFFER_TIMESTAMP_IS_VALID(buffer)) {
- wfd_sink_warning("buffer timestamp is invalid.");
- return GST_PAD_PROBE_OK;
- }
-
- if (g_strrstr(GST_OBJECT_NAME(pad), "audio")) {
- if (wfd_sink->pipeline && wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst)
- g_object_get(G_OBJECT(wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst), "ts-offset", &ts_offset, NULL);
- } else if (g_strrstr(GST_OBJECT_NAME(pad), "video")) {
- if (wfd_sink->pipeline && wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst)
- g_object_get(G_OBJECT(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst), "ts-offset", &ts_offset, NULL);
- }
-
- render_time = GST_BUFFER_TIMESTAMP(buffer);
- render_time += ts_offset;
-
- /* chekc this buffer could be rendered or not */
- if (GST_CLOCK_TIME_IS_VALID(running_time) && GST_CLOCK_TIME_IS_VALID(render_time)) {
- diff = GST_CLOCK_DIFF(running_time, render_time);
- if (diff < 0) {
- /* this buffer could be NOT rendered */
- wfd_sink_debug("%s : diff time : -%" GST_TIME_FORMAT "",
- GST_STR_NULL((GST_OBJECT_NAME(pad))),
- GST_TIME_ARGS(GST_CLOCK_DIFF(render_time, running_time)));
- } else {
- /* this buffer could be rendered */
- /*wfd_sink_debug ("%s :diff time : %" GST_TIME_FORMAT "\n", */
- /* GST_STR_NULL((GST_OBJECT_NAME(pad))), */
- /* GST_TIME_ARGS(diff)); */
- }
- }
-
- /* update buffer count and gap */
- if (g_strrstr(GST_OBJECT_NAME(pad), "video")) {
- wfd_sink->video_buffer_count++;
- wfd_sink->video_accumulated_gap += diff;
- } else if (g_strrstr(GST_OBJECT_NAME(pad), "audio")) {
- wfd_sink->audio_buffer_count++;
- wfd_sink->audio_accumulated_gap += diff;
- } else {
- wfd_sink_warning("invalid buffer type.. ");
- return GST_PAD_PROBE_DROP;
- }
-
- if (GST_CLOCK_TIME_IS_VALID(wfd_sink->last_buffer_timestamp)) {
- /* fisrt 60sec, just calculate the gap between source device and sink device */
- if (GST_BUFFER_TIMESTAMP(buffer) < 60 * GST_SECOND)
- return GST_PAD_PROBE_OK;
-
- /* every 10sec, calculate the gap between source device and sink device */
- if (GST_CLOCK_DIFF(wfd_sink->last_buffer_timestamp, GST_BUFFER_TIMESTAMP(buffer))
- > COMPENSATION_CHECK_PERIOD) {
- gint64 audio_avgrage_gap = 0LL;
- gint64 video_avgrage_gap = 0LL;
- gint64 audio_avgrage_gap_diff = 0LL;
- gint64 video_avgrage_gap_diff = 0LL;
- gboolean video_minus_compensation = FALSE;
- gboolean audio_minus_compensation = FALSE;
- gint64 avgrage_gap_diff = 0LL;
- gboolean minus_compensation = FALSE;
-
- /* check video */
- if (wfd_sink->video_buffer_count > 0) {
- video_avgrage_gap = wfd_sink->video_accumulated_gap / wfd_sink->video_buffer_count;
-
- if (wfd_sink->video_average_gap != 0) {
- if (video_avgrage_gap > wfd_sink->video_average_gap) {
- video_avgrage_gap_diff = video_avgrage_gap - wfd_sink->video_average_gap;
- video_minus_compensation = TRUE;
- } else {
- video_avgrage_gap_diff = wfd_sink->video_average_gap - video_avgrage_gap;
- video_minus_compensation = FALSE;
- }
- } else {
- wfd_sink_debug("first update video average gap(%lld) ", video_avgrage_gap);
- wfd_sink->video_average_gap = video_avgrage_gap;
- }
- } else {
- wfd_sink_debug("there is no video buffer flow during %"GST_TIME_FORMAT
- " ~ %" GST_TIME_FORMAT"",
- GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
- GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
- }
-
- /* check audio */
- if (wfd_sink->audio_buffer_count > 0) {
- audio_avgrage_gap = wfd_sink->audio_accumulated_gap / wfd_sink->audio_buffer_count;
-
- if (wfd_sink->audio_average_gap != 0) {
- if (audio_avgrage_gap > wfd_sink->audio_average_gap) {
- audio_avgrage_gap_diff = audio_avgrage_gap - wfd_sink->audio_average_gap;
- audio_minus_compensation = TRUE;
- } else {
- audio_avgrage_gap_diff = wfd_sink->audio_average_gap - audio_avgrage_gap;
- audio_minus_compensation = FALSE;
- }
- } else {
- wfd_sink_debug("first update audio average gap(%lld) ", audio_avgrage_gap);
- wfd_sink->audio_average_gap = audio_avgrage_gap;
- }
- } else {
- wfd_sink_debug("there is no audio buffer flow during %"GST_TIME_FORMAT
- " ~ %" GST_TIME_FORMAT"",
- GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
- GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
- }
-
- /* selecet average_gap_diff between video and audio */
- /* which makes no buffer drop in the sink elements */
- if (video_avgrage_gap_diff && audio_avgrage_gap_diff) {
- if (!video_minus_compensation && !audio_minus_compensation) {
- minus_compensation = FALSE;
- if (video_avgrage_gap_diff > audio_avgrage_gap_diff)
- avgrage_gap_diff = video_avgrage_gap_diff;
- else
- avgrage_gap_diff = audio_avgrage_gap_diff;
- } else if (video_minus_compensation && audio_minus_compensation) {
- minus_compensation = TRUE;
- if (video_avgrage_gap_diff > audio_avgrage_gap_diff)
- avgrage_gap_diff = audio_avgrage_gap_diff;
- else
- avgrage_gap_diff = video_avgrage_gap_diff;
- } else {
- minus_compensation = FALSE;
- if (!video_minus_compensation)
- avgrage_gap_diff = video_avgrage_gap_diff;
- else
- avgrage_gap_diff = audio_avgrage_gap_diff;
- }
- } else if (video_avgrage_gap_diff) {
- minus_compensation = video_minus_compensation;
- avgrage_gap_diff = video_avgrage_gap_diff;
- } else if (audio_avgrage_gap_diff) {
- minus_compensation = audio_minus_compensation;
- avgrage_gap_diff = audio_avgrage_gap_diff;
- }
-
- wfd_sink_debug("average diff gap difference beween audio:%s%lld and video:%s%lld ",
- audio_minus_compensation ? "-" : "", audio_avgrage_gap_diff,
- video_minus_compensation ? "-" : "", video_avgrage_gap_diff);
-
-
- /* if calculated gap diff is larger than 1ms. need to compensate buffer timestamp */
- if (avgrage_gap_diff >= COMPENSATION_CRETERIA_VALUE) {
- if (minus_compensation)
- ts_offset -= avgrage_gap_diff;
- else
- ts_offset += avgrage_gap_diff;
-
- wfd_sink_debug("do timestamp compensation : %s%lld (ts-offset : %"
- GST_TIME_FORMAT") at(%" GST_TIME_FORMAT")",
- minus_compensation ? "-" : "", avgrage_gap_diff,
- GST_TIME_ARGS(ts_offset), GST_TIME_ARGS(running_time));
-
- if (wfd_sink->pipeline && wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst)
- g_object_set(G_OBJECT(wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst), "ts-offset", (gint64)ts_offset, NULL);
- if (wfd_sink->pipeline && wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst)
- g_object_set(G_OBJECT(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst), "ts-offset", (gint64)ts_offset, NULL);
- } else {
- wfd_sink_debug("don't need to do timestamp compensation : %s%lld (ts-offset : %"GST_TIME_FORMAT ")",
- minus_compensation ? "-" : "", avgrage_gap_diff, GST_TIME_ARGS(ts_offset));
- }
-
- /* reset values*/
- wfd_sink->video_buffer_count = 0;
- wfd_sink->video_accumulated_gap = 0LL;
- wfd_sink->audio_buffer_count = 0;
- wfd_sink->audio_accumulated_gap = 0LL;
- wfd_sink->last_buffer_timestamp = GST_BUFFER_TIMESTAMP(buffer);
- }
- } else {
- wfd_sink_debug("first update last buffer timestamp :%" GST_TIME_FORMAT,
- GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
- wfd_sink->last_buffer_timestamp = GST_BUFFER_TIMESTAMP(buffer);
- }
-
- return GST_PAD_PROBE_OK;
-}
-
-
-static void
-__mm_wfd_sink_demux_pad_added(GstElement *ele, GstPad *pad, gpointer data)
-{
- mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
- gchar *name = gst_pad_get_name(pad);
- GstElement *pipeline = NULL;
- GstElement *decodebin = NULL;
- GstElement *sinkbin = NULL;
- GstPad *sinkpad = NULL;
- GstPad *srcpad = NULL;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
-
- pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
-
- /* take decodebin/sinkbin */
- if (name[0] == 'v') {
- wfd_sink_debug("=========== >>>>>>>>>> Received VIDEO pad...");
-
- MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL, NULL);
-
- gst_pad_add_probe(pad,
- GST_PAD_PROBE_TYPE_BUFFER,
- _mm_wfd_sink_check_running_time,
- (gpointer)wfd_sink,
- NULL);
-
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink)) {
- wfd_sink_error("failed to prepare video pipeline....");
- goto ERROR;
- }
-
- if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst)
- decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
- if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst)
- sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
- } else if (name[0] == 'a') {
- wfd_sink_debug("=========== >>>>>>>>>> Received AUDIO pad...");
-
- MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL, NULL);
-
- gst_pad_add_probe(pad,
- GST_PAD_PROBE_TYPE_BUFFER,
- _mm_wfd_sink_check_running_time,
- (gpointer)wfd_sink,
- NULL);
-
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink)) {
- wfd_sink_error("failed to prepare audio pipeline....");
- goto ERROR;
- }
-
- if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst)
- decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
- if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst)
- sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
- } else {
- wfd_sink_error("unexceptable pad is added!!!");
- return;
- }
-
- srcpad = gst_object_ref(pad);
-
- /* add decodebin and link */
- if (decodebin) {
- if (!gst_bin_add(GST_BIN(pipeline), decodebin)) {
- wfd_sink_error("failed to add %s to pipeline",
- GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
- goto ERROR;
- }
-
- sinkpad = gst_element_get_static_pad(decodebin, "sink");
- if (!sinkpad) {
- wfd_sink_error("failed to get sink pad from %s",
- GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
- goto ERROR;
- }
-
- if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
- wfd_sink_error("failed to link %s and %s",
- GST_STR_NULL(GST_PAD_NAME(srcpad)),
- GST_STR_NULL(GST_PAD_NAME(sinkpad)));
- goto ERROR;
- }
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
-
- srcpad = gst_element_get_static_pad(decodebin, "src");
- if (!srcpad) {
- wfd_sink_error("failed to get src pad from %s",
- GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
- goto ERROR;
- }
- } else {
- wfd_sink_warning("going on without decodebin...");
- }
-
- /* add sinkbin and link */
- if (sinkbin) {
- if (!gst_bin_add(GST_BIN(pipeline), sinkbin)) {
- wfd_sink_error("failed to add %s to pipeline",
- GST_STR_NULL(GST_ELEMENT_NAME(sinkbin)));
- goto ERROR;
- }
-
- sinkpad = gst_element_get_static_pad(sinkbin, "sink");
- if (!sinkpad) {
- wfd_sink_error("failed to get sink pad from %s",
- GST_STR_NULL(GST_ELEMENT_NAME(sinkbin)));
- goto ERROR;
- }
-
- if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
- wfd_sink_error("failed to link %s and %s",
- GST_STR_NULL(GST_PAD_NAME(srcpad)),
- GST_STR_NULL(GST_PAD_NAME(sinkpad)));
- goto ERROR;
- }
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
- } else {
- wfd_sink_error("there is no sinkbin...");
- goto ERROR;
- }
-
-
- /* run */
- if (decodebin) {
- if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(decodebin))) {
- wfd_sink_error("failed to sync %s state with parent",
- GST_STR_NULL(GST_PAD_NAME(decodebin)));
- goto ERROR;
- }
- }
-
- if (sinkbin) {
- if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(sinkbin))) {
- wfd_sink_error("failed to sync %s state with parent",
- GST_STR_NULL(GST_PAD_NAME(sinkbin)));
- goto ERROR;
- }
- }
-
- if (name[0] == 'v') {
- MMWFDSINK_GENERATE_DOT_IF_ENABLED(wfd_sink, "video-pad-added-pipeline");
- } else if (name[0] == 'a') {
- MMWFDSINK_GENERATE_DOT_IF_ENABLED(wfd_sink, "audio-pad-added-pipeline");
- }
-
- MMWFDSINK_FREEIF(name);
-
- wfd_sink_debug_fleave();
-
- return;
-
- /* ERRORS */
-ERROR:
- MMWFDSINK_FREEIF(name);
-
- if (srcpad)
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
-
- if (sinkpad)
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
-
- /* need to notify to app */
- MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
-
- return;
-}
-
-static void
-__mm_wfd_sink_change_av_format(GstElement *wfdsrc, gpointer *need_to_flush, gpointer data)
-{
- mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_if_fail(wfd_sink);
- wfd_sink_return_if_fail(need_to_flush);
-
- if (MMWFDSINK_CURRENT_STATE(wfd_sink) == MM_WFD_SINK_STATE_PLAYING) {
- wfd_sink_debug("need to flush pipeline");
- *need_to_flush = (gpointer) TRUE;
- } else {
- wfd_sink_debug("don't need to flush pipeline");
- *need_to_flush = (gpointer) FALSE;
- }
-
-
- wfd_sink_debug_fleave();
-}
-
-
-static void
-__mm_wfd_sink_update_stream_info(GstElement *wfdsrc, GstStructure *str, gpointer data)
-{
- mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
- MMWFDSinkStreamInfo *stream_info = NULL;
- gint is_valid_audio_format = FALSE;
- gint is_valid_video_format = FALSE;
- gint audio_codec = MM_WFD_SINK_AUDIO_CODEC_NONE;
- gint video_codec = MM_WFD_SINK_VIDEO_CODEC_NONE;
- gchar *audio_format;
- gchar *video_format;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_if_fail(str && GST_IS_STRUCTURE(str));
- wfd_sink_return_if_fail(wfd_sink);
-
- stream_info = &wfd_sink->stream_info;
-
- audio_codec = wfd_sink->stream_info.audio_stream_info.codec;
- video_codec = wfd_sink->stream_info.video_stream_info.codec;
-
- if (gst_structure_has_field(str, "audio_format")) {
- is_valid_audio_format = TRUE;
- audio_format = g_strdup(gst_structure_get_string(str, "audio_format"));
- if (g_strrstr(audio_format, "AAC"))
- stream_info->audio_stream_info.codec = MM_WFD_SINK_AUDIO_CODEC_AAC;
- else if (g_strrstr(audio_format, "AC3"))
- stream_info->audio_stream_info.codec = MM_WFD_SINK_AUDIO_CODEC_AC3;
- else if (g_strrstr(audio_format, "LPCM"))
- stream_info->audio_stream_info.codec = MM_WFD_SINK_AUDIO_CODEC_LPCM;
- else {
- wfd_sink_error("invalid audio format(%s)...", audio_format);
- is_valid_audio_format = FALSE;
- }
-
- if (is_valid_audio_format == TRUE) {
- if (gst_structure_has_field(str, "audio_rate"))
- gst_structure_get_int(str, "audio_rate", &stream_info->audio_stream_info.sample_rate);
- if (gst_structure_has_field(str, "audio_channels"))
- gst_structure_get_int(str, "audio_channels", &stream_info->audio_stream_info.channels);
- if (gst_structure_has_field(str, "audio_bitwidth"))
- gst_structure_get_int(str, "audio_bitwidth", &stream_info->audio_stream_info.bitwidth);
-
- if (audio_codec != MM_WFD_SINK_AUDIO_CODEC_NONE) {
- if (audio_codec != stream_info->audio_stream_info.codec) {
- wfd_sink_debug("audio codec is changed...need to change audio decodebin");
- }
- } else {
- WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE);
- }
-
- wfd_sink_debug("audio_format : %s \n \t rate : %d \n \t channels : %d \n \t bitwidth : %d \n \t",
- audio_format,
- stream_info->audio_stream_info.sample_rate,
- stream_info->audio_stream_info.channels,
- stream_info->audio_stream_info.bitwidth);
- }
- }
-
- if (gst_structure_has_field(str, "video_format")) {
- is_valid_video_format = TRUE;
- video_format = g_strdup(gst_structure_get_string(str, "video_format"));
- if (!g_strrstr(video_format, "H264")) {
- wfd_sink_error("invalid video format(%s)...", video_format);
- is_valid_video_format = FALSE;
- }
-
- if (is_valid_video_format == TRUE) {
- stream_info->video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_H264;
-
- if (gst_structure_has_field(str, "video_width"))
- gst_structure_get_int(str, "video_width", &stream_info->video_stream_info.width);
- if (gst_structure_has_field(str, "video_height"))
- gst_structure_get_int(str, "video_height", &stream_info->video_stream_info.height);
- if (gst_structure_has_field(str, "video_framerate"))
- gst_structure_get_int(str, "video_framerate", &stream_info->video_stream_info.frame_rate);
-
- if (video_codec != MM_WFD_SINK_AUDIO_CODEC_NONE) {
- if (video_codec != stream_info->video_stream_info.codec) {
- wfd_sink_debug("video codec is changed...need to change video decodebin");
- }
- } else {
- WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE);
- }
-
- wfd_sink_debug("video_format : %s \n \t width : %d \n \t height : %d \n \t frame_rate : %d \n \t",
- video_format,
- stream_info->video_stream_info.width,
- stream_info->video_stream_info.height,
- stream_info->video_stream_info.frame_rate);
- }
- }
-
- WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
-
- wfd_sink_debug_fleave();
-}
-
-static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfdsrc)
-{
- GstStructure *audio_param = NULL;
- GstStructure *video_param = NULL;
- GstStructure *hdcp_param = NULL;
- gint hdcp_version = 0;
- gint hdcp_port = 0;
- guint CEA_resolution = 0;
- guint VESA_resolution = 0;
- guint HH_resolution = 0;
- GObjectClass *klass;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(wfdsrc, MM_ERROR_WFD_NOT_INITIALIZED);
-
- klass = G_OBJECT_GET_CLASS(G_OBJECT(wfdsrc));
-
- g_object_set(G_OBJECT(wfdsrc), "debug", wfd_sink->ini.set_debug_property, NULL);
- g_object_set(G_OBJECT(wfdsrc), "enable-pad-probe", wfd_sink->ini.enable_wfdsrc_pad_probe, NULL);
- if (g_object_class_find_property(klass, "udp-buffer-size"))
- g_object_set(G_OBJECT(wfdsrc), "udp-buffer-size", 2097152, NULL);
- if (g_object_class_find_property(klass, "do-request"))
- g_object_set(G_OBJECT(wfdsrc), "do-request", wfd_sink->ini.enable_retransmission, NULL);
- if (g_object_class_find_property(klass, "latency"))
- g_object_set(G_OBJECT(wfdsrc), "latency", wfd_sink->ini.jitter_buffer_latency, NULL);
-
- audio_param = gst_structure_new("audio_param",
- "audio_codec", G_TYPE_UINT, wfd_sink->ini.audio_codec,
- "audio_latency", G_TYPE_UINT, wfd_sink->ini.audio_latency,
- "audio_channels", G_TYPE_UINT, wfd_sink->ini.audio_channel,
- "audio_sampling_frequency", G_TYPE_UINT, wfd_sink->ini.audio_sampling_frequency,
- NULL);
-
- CEA_resolution = wfd_sink->ini.video_cea_support;
- VESA_resolution = wfd_sink->ini.video_vesa_support;
- HH_resolution = wfd_sink->ini.video_hh_support;
-
- __mm_wfd_sink_prepare_video_resolution(wfd_sink->supportive_resolution, &CEA_resolution, &VESA_resolution, &HH_resolution);
-
- wfd_sink_debug("set video resolution CEA[%x] VESA[%x] HH[%x]", CEA_resolution, VESA_resolution, HH_resolution);
-
- video_param = gst_structure_new("video_param",
- "video_codec", G_TYPE_UINT, wfd_sink->ini.video_codec,
- "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.video_native_resolution,
- "video_cea_support", G_TYPE_UINT, CEA_resolution,
- "video_vesa_support", G_TYPE_UINT, VESA_resolution,
- "video_hh_support", G_TYPE_UINT, HH_resolution,
- "video_profile", G_TYPE_UINT, wfd_sink->ini.video_profile,
- "video_level", G_TYPE_UINT, wfd_sink->ini.video_level,
- "video_latency", G_TYPE_UINT, wfd_sink->ini.video_latency,
- "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.video_vertical_resolution,
- "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.video_horizontal_resolution,
- "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.video_minimum_slicing,
- "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.video_slice_enc_param,
- "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.video_framerate_control_support,
- NULL);
-
- mm_attrs_get_int_by_name(wfd_sink->attrs, "hdcp_version", &hdcp_version);
- mm_attrs_get_int_by_name(wfd_sink->attrs, "hdcp_port", &hdcp_port);
- wfd_sink_debug("set hdcp version %d with %d port", hdcp_version, hdcp_port);
-
- hdcp_param = gst_structure_new("hdcp_param",
- "hdcp_version", G_TYPE_INT, hdcp_version,
- "hdcp_port_no", G_TYPE_INT, hdcp_port,
- NULL);
-
- g_object_set(G_OBJECT(wfdsrc), "audio-param", audio_param, NULL);
- g_object_set(G_OBJECT(wfdsrc), "video-param", video_param, NULL);
- g_object_set(G_OBJECT(wfdsrc), "hdcp-param", hdcp_param, NULL);
-
- g_signal_connect(wfdsrc, "update-media-info", G_CALLBACK(__mm_wfd_sink_update_stream_info), wfd_sink);
-
- g_signal_connect(wfdsrc, "change-av-format", G_CALLBACK(__mm_wfd_sink_change_av_format), wfd_sink);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_prepare_demux(mm_wfd_sink_t *wfd_sink, GstElement *demux)
-{
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(demux, MM_ERROR_WFD_NOT_INITIALIZED);
-
- g_signal_connect(demux, "pad-added", G_CALLBACK(__mm_wfd_sink_demux_pad_added), wfd_sink);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static void __mm_wfd_sink_queue_overrun(GstElement *element, gpointer u_data)
-{
- wfd_sink_debug_fenter();
-
- return_if_fail(element);
-
- wfd_sink_warning("%s is overrun",
- GST_STR_NULL(GST_ELEMENT_NAME(element)));
-
- wfd_sink_debug_fleave();
-
- return;
-}
-
-static void __mm_wfd_sink_prepare_queue(mm_wfd_sink_t *wfd_sink, GstElement *queue)
-{
- wfd_sink_debug_fenter();
-
- wfd_sink_return_if_fail(wfd_sink);
- wfd_sink_return_if_fail(queue);
-
- /* set maximum buffer size of queue as 3sec */
- g_object_set(G_OBJECT(queue), "max-size-bytes", 0, NULL);
- g_object_set(G_OBJECT(queue), "max-size-buffers", 0, NULL);
- g_object_set(G_OBJECT(queue), "max-size-time", (guint64)3000000000ULL, NULL);
- g_signal_connect(queue, "overrun", G_CALLBACK(__mm_wfd_sink_queue_overrun), wfd_sink);
-
- wfd_sink_debug_fleave();
-
- return;
-}
-
-
-static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink)
-{
- MMWFDSinkGstElement *mainbin = NULL;
- GList *element_bucket = NULL;
- GstBus *bus = NULL;
- int i;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
- wfd_sink_return_val_if_fail(wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* Create pipeline */
- wfd_sink->pipeline = (MMWFDSinkGstPipelineInfo *) g_malloc0(sizeof(MMWFDSinkGstPipelineInfo));
- if (wfd_sink->pipeline == NULL)
- goto CREATE_ERROR;
-
- memset(wfd_sink->pipeline, 0, sizeof(MMWFDSinkGstPipelineInfo));
-
- /* create mainbin */
- mainbin = (MMWFDSinkGstElement *) g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_M_NUM);
- if (mainbin == NULL)
- goto CREATE_ERROR;
-
- memset(mainbin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_M_NUM);
-
- /* create pipeline */
- mainbin[WFD_SINK_M_PIPE].id = WFD_SINK_M_PIPE;
- mainbin[WFD_SINK_M_PIPE].gst = gst_pipeline_new("wfdsink");
- if (!mainbin[WFD_SINK_M_PIPE].gst) {
- wfd_sink_error("failed to create pipeline");
- goto CREATE_ERROR;
- }
-
- /* create wfdsrc */
- MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_SRC, wfd_sink->ini.name_of_source, "wfdsink_source", TRUE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_SRC].gst, "src");
- if (mainbin[WFD_SINK_M_SRC].gst) {
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_source(wfd_sink, mainbin[WFD_SINK_M_SRC].gst)) {
- wfd_sink_error("failed to prepare wfdsrc...");
- goto CREATE_ERROR;
- }
- }
-
- /* create rtpmp2tdepay */
- MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_DEPAY, "rtpmp2tdepay", "wfdsink_depay", TRUE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_DEPAY].gst, "src");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_DEPAY].gst, "sink");
-
- MMWFDSINK_TS_DATA_DUMP(wfd_sink, mainbin[WFD_SINK_M_DEPAY].gst, "src");
-
- /* create tsdemuxer*/
- MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_DEMUX, wfd_sink->ini.name_of_tsdemux, "wfdsink_demux", TRUE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_DEMUX].gst, "sink");
- if (mainbin[WFD_SINK_M_DEMUX].gst) {
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_demux(wfd_sink, mainbin[WFD_SINK_M_DEMUX].gst)) {
- wfd_sink_error("failed to prepare demux...");
- goto CREATE_ERROR;
- }
- }
-
- /* adding created elements to pipeline */
- if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(mainbin[WFD_SINK_M_PIPE].gst), element_bucket, FALSE)) {
- wfd_sink_error("failed to add elements");
- goto CREATE_ERROR;
- }
-
- /* linking elements in the bucket by added order. */
- if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
- wfd_sink_error("failed to link elements");
- goto CREATE_ERROR;
- }
-
- /* connect bus callback */
- bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[WFD_SINK_M_PIPE].gst));
- if (!bus) {
- wfd_sink_error("cannot get bus from pipeline.");
- goto CREATE_ERROR;
- }
-
- /* add bus message callback*/
- gst_bus_add_watch(bus, (GstBusFunc)_mm_wfd_sink_msg_callback, wfd_sink);
-
- /* set sync handler to get tag synchronously */
- gst_bus_set_sync_handler(bus, _mm_wfd_bus_sync_callback, wfd_sink, NULL);
-
- g_list_free(element_bucket);
- gst_object_unref(GST_OBJECT(bus));
-
- /* now we have completed mainbin. take it */
- wfd_sink->pipeline->mainbin = mainbin;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
- /* ERRORS */
-CREATE_ERROR:
- wfd_sink_error("ERROR : releasing pipeline");
-
- if (element_bucket)
- g_list_free(element_bucket);
- element_bucket = NULL;
-
- /* finished */
- if (bus)
- gst_object_unref(GST_OBJECT(bus));
- bus = NULL;
-
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_M_NUM; i++) { /* NOTE : skip pipeline */
- if (mainbin != NULL && mainbin[i].gst) {
- GstObject *parent = NULL;
- parent = gst_element_get_parent(mainbin[i].gst);
-
- if (!parent) {
- gst_object_unref(GST_OBJECT(mainbin[i].gst));
- mainbin[i].gst = NULL;
- } else {
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
-
- /* release mainbin with it's childs */
- if (mainbin != NULL && mainbin[WFD_SINK_M_PIPE].gst)
- gst_object_unref(GST_OBJECT(mainbin[WFD_SINK_M_PIPE].gst));
-
- MMWFDSINK_FREEIF(mainbin);
-
- MMWFDSINK_FREEIF(wfd_sink->pipeline);
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
-{
- MMWFDSinkGstElement *a_decodebin = NULL;
- MMWFDSinkGstElement *first_element = NULL;
- MMWFDSinkGstElement *last_element = NULL;
- GList *element_bucket = NULL;
- GstPad *sinkpad = NULL;
- GstPad *srcpad = NULL;
- GstPad *ghostpad = NULL;
- GList *first_list = NULL;
- GList *last_list = NULL;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->a_decodebin &&
- wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- if (wfd_sink->audio_decodebin_is_linked) {
- wfd_sink_debug("audio decodebin is already linked... nothing to do");
- return MM_ERROR_NONE;
- }
-
- /* take audio decodebin */
- a_decodebin = wfd_sink->pipeline->a_decodebin;
-
- /* check audio queue */
- if (a_decodebin[WFD_SINK_A_D_QUEUE].gst)
- element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_QUEUE]);
-
- /* check audio hdcp */
- if (a_decodebin[WFD_SINK_A_D_HDCP].gst)
- element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_HDCP]);
-
- /* check audio codec */
- switch (wfd_sink->stream_info.audio_stream_info.codec) {
- case MM_WFD_SINK_AUDIO_CODEC_LPCM:
- if (a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst)
- element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER]);
- if (a_decodebin[WFD_SINK_A_D_LPCM_FILTER].gst) {
- GstCaps *caps = NULL;
- element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_LPCM_FILTER]);
- caps = gst_caps_new_simple("audio/x-raw",
- "rate", G_TYPE_INT, wfd_sink->stream_info.audio_stream_info.sample_rate,
- "channels", G_TYPE_INT, wfd_sink->stream_info.audio_stream_info.channels,
- "format", G_TYPE_STRING, "S16BE", NULL);
-
- g_object_set(G_OBJECT(a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst), "caps", caps, NULL);
- gst_object_unref(GST_OBJECT(caps));
- }
- break;
-
- case MM_WFD_SINK_AUDIO_CODEC_AAC:
- if (a_decodebin[WFD_SINK_A_D_AAC_PARSE].gst)
- element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AAC_PARSE]);
- if (a_decodebin[WFD_SINK_A_D_AAC_DEC].gst)
- element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AAC_DEC]);
- break;
-
- case MM_WFD_SINK_AUDIO_CODEC_AC3:
- if (a_decodebin[WFD_SINK_A_D_AC3_PARSE].gst)
- element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AC3_PARSE]);
- if (a_decodebin[WFD_SINK_A_D_AC3_DEC].gst)
- element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AC3_DEC]);
- break;
-
- default:
- wfd_sink_error("audio codec is not decied yet. cannot link audio decodebin...");
- return MM_ERROR_WFD_INTERNAL;
- break;
- }
-
- if (element_bucket == NULL) {
- wfd_sink_error("there are no elements to be linked in the audio decodebin, destroy it");
- if (MM_ERROR_NONE != __mm_wfd_sink_destroy_audio_decodebin(wfd_sink)) {
- wfd_sink_error("failed to destroy audio decodebin");
- goto fail_to_link;
- }
- goto done;
- }
-
- /* adding elements to audio decodebin */
- if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(a_decodebin[WFD_SINK_A_D_BIN].gst), element_bucket, FALSE)) {
- wfd_sink_error("failed to add elements to audio decodebin");
- goto fail_to_link;
- }
-
- /* linking elements in the bucket by added order. */
- if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
- wfd_sink_error("failed to link elements of the audio decodebin");
- goto fail_to_link;
- }
-
- /* get first element's sinkpad for creating ghostpad */
- first_list = g_list_first(element_bucket);
- if (first_list == NULL) {
- wfd_sink_error("failed to get first list of the element_bucket");
- goto fail_to_link;
- }
-
- first_element = (MMWFDSinkGstElement *)first_list->data;
- if (!first_element) {
- wfd_sink_error("failed to get first element of the audio decodebin");
- goto fail_to_link;
- }
-
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
- if (!sinkpad) {
- wfd_sink_error("failed to get sink pad from element(%s)",
- GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
- goto fail_to_link;
- }
-
- ghostpad = gst_ghost_pad_new("sink", sinkpad);
- if (!ghostpad) {
- wfd_sink_error("failed to create ghostpad of audio decodebin");
- goto fail_to_link;
- }
-
- if (FALSE == gst_element_add_pad(a_decodebin[WFD_SINK_A_D_BIN].gst, ghostpad)) {
- wfd_sink_error("failed to add ghostpad to audio decodebin");
- goto fail_to_link;
- }
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
-
-
- /* get last element's src for creating ghostpad */
- last_list = g_list_last(element_bucket);
- if (last_list == NULL) {
- wfd_sink_error("failed to get last list of the element_bucket");
- goto fail_to_link;
- }
-
- last_element = (MMWFDSinkGstElement *)last_list->data;
- if (!last_element) {
- wfd_sink_error("failed to get last element of the audio decodebin");
- goto fail_to_link;
- }
-
- srcpad = gst_element_get_static_pad(GST_ELEMENT(last_element->gst), "src");
- if (!srcpad) {
- wfd_sink_error("failed to get src pad from element(%s)",
- GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
- goto fail_to_link;
- }
-
- ghostpad = gst_ghost_pad_new("src", srcpad);
- if (!ghostpad) {
- wfd_sink_error("failed to create ghostpad of audio decodebin");
- goto fail_to_link;
- }
-
- if (FALSE == gst_element_add_pad(a_decodebin[WFD_SINK_A_D_BIN].gst, ghostpad)) {
- wfd_sink_error("failed to add ghostpad to audio decodebin");
- goto fail_to_link;
- }
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
-
- g_list_free(element_bucket);
-
-done:
- wfd_sink->audio_decodebin_is_linked = TRUE;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
- /* ERRORS*/
-fail_to_link:
- if (srcpad)
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
-
- if (sinkpad)
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
-
- g_list_free(element_bucket);
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-static int __mm_wfd_sink_prepare_audiosink(mm_wfd_sink_t *wfd_sink, GstElement *audio_sink)
-{
- wfd_sink_debug_fenter();
-
- /* check audiosink is created */
- wfd_sink_return_val_if_fail(audio_sink, MM_ERROR_WFD_INVALID_ARGUMENT);
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- g_object_set(G_OBJECT(audio_sink), "provide-clock", FALSE, NULL);
- g_object_set(G_OBJECT(audio_sink), "buffer-time", 100000LL, NULL);
- g_object_set(G_OBJECT(audio_sink), "slave-method", 2, NULL);
- g_object_set(G_OBJECT(audio_sink), "async", wfd_sink->ini.audio_sink_async, NULL);
- g_object_set(G_OBJECT(audio_sink), "ts-offset", (gint64)wfd_sink->ini.sink_ts_offset, NULL);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- MMWFDSinkGstElement *a_decodebin = NULL;
- GstObject *parent = NULL;
- int i;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- if (wfd_sink->pipeline &&
- wfd_sink->pipeline->a_decodebin &&
- wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
- a_decodebin = wfd_sink->pipeline->a_decodebin;
- } else {
- wfd_sink_debug("audio decodebin is not created, nothing to destroy");
- return MM_ERROR_NONE;
- }
-
- parent = gst_element_get_parent(a_decodebin[WFD_SINK_A_D_BIN].gst);
- if (!parent) {
- wfd_sink_debug("audio decodebin has no parent.. need to relase by itself");
-
- if (GST_STATE(a_decodebin[WFD_SINK_A_D_BIN].gst) >= GST_STATE_READY) {
- wfd_sink_debug("try to change state of audio decodebin to NULL");
- ret = gst_element_set_state(a_decodebin[WFD_SINK_A_D_BIN].gst, GST_STATE_NULL);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- wfd_sink_error("failed to change state of audio decodebin to NULL");
- return MM_ERROR_WFD_INTERNAL;
- }
- }
-
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_A_D_NUM; i++) { /* NOTE : skip bin */
- if (a_decodebin[i].gst) {
- parent = gst_element_get_parent(a_decodebin[i].gst);
- if (!parent) {
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
- ((GObject *) a_decodebin[i].gst)->ref_count);
- gst_object_unref(GST_OBJECT(a_decodebin[i].gst));
- a_decodebin[i].gst = NULL;
- } else {
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
- ((GObject *) a_decodebin[i].gst)->ref_count);
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
-
- /* release audio decodebin with it's childs */
- if (a_decodebin[WFD_SINK_A_D_BIN].gst)
- gst_object_unref(GST_OBJECT(a_decodebin[WFD_SINK_A_D_BIN].gst));
-
- } else {
- wfd_sink_debug("audio decodebin has parent(%s), unref it ",
- GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
-
- gst_object_unref(GST_OBJECT(parent));
- }
-
- wfd_sink->audio_decodebin_is_linked = FALSE;
-
- MMWFDSINK_FREEIF(wfd_sink->pipeline->a_decodebin);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
-{
- MMWFDSinkGstElement *a_decodebin = NULL;
- gint audio_codec = WFD_AUDIO_UNKNOWN;
- GList *element_bucket = NULL;
- gboolean link = TRUE;
- gint i = 0;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* check audio decodebin could be linked now */
- switch (wfd_sink->stream_info.audio_stream_info.codec) {
- case MM_WFD_SINK_AUDIO_CODEC_AAC:
- audio_codec = WFD_AUDIO_AAC;
- link = TRUE;
- break;
- case MM_WFD_SINK_AUDIO_CODEC_AC3:
- audio_codec = WFD_AUDIO_AC3;
- link = TRUE;
- break;
- case MM_WFD_SINK_AUDIO_CODEC_LPCM:
- audio_codec = WFD_AUDIO_LPCM;
- link = TRUE;
- break;
- case MM_WFD_SINK_AUDIO_CODEC_NONE:
- default:
- wfd_sink_debug("audio decodebin could NOT be linked now, just create");
- audio_codec = wfd_sink->ini.audio_codec;
- link = FALSE;
- break;
- }
-
- /* alloc handles */
- a_decodebin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_A_D_NUM);
- if (!a_decodebin) {
- wfd_sink_error("failed to allocate memory for audio decodebin");
- return MM_ERROR_WFD_NO_FREE_SPACE;
- }
-
- memset(a_decodebin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_A_D_NUM);
-
- /* create audio decodebin */
- a_decodebin[WFD_SINK_A_D_BIN].id = WFD_SINK_A_D_BIN;
- a_decodebin[WFD_SINK_A_D_BIN].gst = gst_bin_new("audio_deocebin");
- if (!a_decodebin[WFD_SINK_A_D_BIN].gst) {
- wfd_sink_error("failed to create audio decodebin");
- goto CREATE_ERROR;
- }
-
- /* create queue */
- MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_QUEUE, "queue", "audio_queue", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_QUEUE].gst, "sink");
- if (a_decodebin[WFD_SINK_A_D_QUEUE].gst)
- __mm_wfd_sink_prepare_queue(wfd_sink, a_decodebin[WFD_SINK_A_D_QUEUE].gst);
-
- /* create hdcp */
- MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_HDCP, wfd_sink->ini.name_of_audio_hdcp, "audio_hdcp", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_HDCP].gst, "sink");
-
- /* create codec */
- audio_codec = wfd_sink->ini.audio_codec;
- if (audio_codec & WFD_AUDIO_LPCM) {
- /* create LPCM converter */
- MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_LPCM_CONVERTER, wfd_sink->ini.name_of_lpcm_converter, "audio_lpcm_convert", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst, "src");
-
- /* create LPCM filter */
- MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_LPCM_FILTER, wfd_sink->ini.name_of_lpcm_filter, "audio_lpcm_filter", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_LPCM_FILTER].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_LPCM_FILTER].gst, "src");
- }
-
- if (audio_codec & WFD_AUDIO_AAC) {
- /* create AAC parse */
- MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_AAC_PARSE, wfd_sink->ini.name_of_aac_parser, "audio_aac_parser", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AAC_PARSE].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AAC_PARSE].gst, "src");
-
- /* create AAC decoder */
- MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_AAC_DEC, wfd_sink->ini.name_of_aac_decoder, "audio_aac_dec", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AAC_DEC].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AAC_DEC].gst, "src");
- }
-
- if (audio_codec & WFD_AUDIO_AC3) {
- /* create AC3 parser */
- MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_AC3_PARSE, wfd_sink->ini.name_of_ac3_parser, "audio_ac3_parser", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AC3_PARSE].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AC3_PARSE].gst, "src");
-
- /* create AC3 decoder */
- MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_AC3_DEC, wfd_sink->ini.name_of_ac3_decoder, "audio_ac3_dec", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AC3_DEC].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AC3_DEC].gst, "src");
- }
-
- g_list_free(element_bucket);
-
- /* take it */
- wfd_sink->pipeline->a_decodebin = a_decodebin;
-
- /* link audio decodebin if audio codec is fixed */
- if (link) {
- if (MM_ERROR_NONE != __mm_wfd_sink_link_audio_decodebin(wfd_sink)) {
- wfd_sink_error("failed to link audio decodebin, destroy audio decodebin");
- __mm_wfd_sink_destroy_audio_decodebin(wfd_sink);
- return MM_ERROR_WFD_INTERNAL;
- }
- }
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
-CREATE_ERROR:
- wfd_sink_error("failed to create audio decodebin, release all");
-
- g_list_free(element_bucket);
-
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_A_D_NUM; i++) { /* NOTE : skip bin */
- if (a_decodebin != NULL && a_decodebin[i].gst) {
- GstObject *parent = NULL;
- parent = gst_element_get_parent(a_decodebin[i].gst);
-
- if (!parent) {
- gst_object_unref(GST_OBJECT(a_decodebin[i].gst));
- a_decodebin[i].gst = NULL;
- } else {
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
-
- /* release audioo decodebin with it's childs */
- if (a_decodebin != NULL && a_decodebin[WFD_SINK_A_D_BIN].gst)
- gst_object_unref(GST_OBJECT(a_decodebin[WFD_SINK_A_D_BIN].gst));
-
- MMWFDSINK_FREEIF(a_decodebin);
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-static int __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- MMWFDSinkGstElement *a_sinkbin = NULL;
- GstObject *parent = NULL;
- int i;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- if (wfd_sink->pipeline &&
- wfd_sink->pipeline->a_sinkbin &&
- wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
- a_sinkbin = wfd_sink->pipeline->a_sinkbin;
- } else {
- wfd_sink_debug("audio sinkbin is not created, nothing to destroy");
- return MM_ERROR_NONE;
- }
-
- parent = gst_element_get_parent(a_sinkbin[WFD_SINK_A_S_BIN].gst);
- if (!parent) {
- wfd_sink_debug("audio decodebin has no parent.. need to relase by itself");
-
- if (GST_STATE(a_sinkbin[WFD_SINK_A_S_BIN].gst) >= GST_STATE_READY) {
- wfd_sink_debug("try to change state of audio decodebin to NULL");
- ret = gst_element_set_state(a_sinkbin[WFD_SINK_A_S_BIN].gst, GST_STATE_NULL);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- wfd_sink_error("failed to change state of audio decodebin to NULL");
- return MM_ERROR_WFD_INTERNAL;
- }
- }
-
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_A_S_NUM; i++) { /* NOTE : skip bin */
- if (a_sinkbin[i].gst) {
- parent = gst_element_get_parent(a_sinkbin[i].gst);
- if (!parent) {
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
- ((GObject *) a_sinkbin[i].gst)->ref_count);
- gst_object_unref(GST_OBJECT(a_sinkbin[i].gst));
- a_sinkbin[i].gst = NULL;
- } else {
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
- ((GObject *) a_sinkbin[i].gst)->ref_count);
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
-
- /* release audio decodebin with it's childs */
- if (a_sinkbin[WFD_SINK_A_S_BIN].gst)
- gst_object_unref(GST_OBJECT(a_sinkbin[WFD_SINK_A_S_BIN].gst));
-
- } else {
- wfd_sink_debug("audio sinkbin has parent(%s), unref it ",
- GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
-
- gst_object_unref(GST_OBJECT(parent));
- }
-
- MMWFDSINK_FREEIF(wfd_sink->pipeline->a_sinkbin);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
-{
- MMWFDSinkGstElement *a_sinkbin = NULL;
- MMWFDSinkGstElement *first_element = NULL;
- GList *element_bucket = NULL;
- GstPad *ghostpad = NULL;
- GstPad *pad = NULL;
- gint i = 0;
- GList *first_list = NULL;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* alloc handles */
- a_sinkbin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_A_S_NUM);
- if (!a_sinkbin) {
- wfd_sink_error("failed to allocate memory for audio sinkbin");
- return MM_ERROR_WFD_NO_FREE_SPACE;
- }
-
- memset(a_sinkbin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_A_S_NUM);
-
- /* create audio sinkbin */
- a_sinkbin[WFD_SINK_A_S_BIN].id = WFD_SINK_A_S_BIN;
- a_sinkbin[WFD_SINK_A_S_BIN].gst = gst_bin_new("audio_sinkbin");
- if (!a_sinkbin[WFD_SINK_A_S_BIN].gst) {
- wfd_sink_error("failed to create audio sinkbin");
- goto CREATE_ERROR;
- }
-
- /* create resampler */
- MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_RESAMPLER, wfd_sink->ini.name_of_audio_resampler, "audio_resampler", TRUE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_RESAMPLER].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_RESAMPLER].gst, "src");
-
- /* create volume */
- MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_VOLUME, wfd_sink->ini.name_of_audio_volume, "audio_volume", TRUE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_VOLUME].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_VOLUME].gst, "src");
-
- /* create sink */
- MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_SINK, wfd_sink->ini.name_of_audio_sink, "audio_sink", TRUE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_SINK].gst, "sink");
- if (a_sinkbin[WFD_SINK_A_S_SINK].gst) {
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audiosink(wfd_sink, a_sinkbin[WFD_SINK_A_S_SINK].gst)) {
- wfd_sink_error("failed to set audio sink property....");
- goto CREATE_ERROR;
- }
- }
-
- /* adding created elements to audio sinkbin */
- if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(a_sinkbin[WFD_SINK_A_S_BIN].gst), element_bucket, FALSE)) {
- wfd_sink_error("failed to add elements to audio sinkbin");
- goto CREATE_ERROR;
- }
-
- /* linking elements in the bucket by added order. */
- if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
- wfd_sink_error("failed to link elements fo the audio sinkbin");
- goto CREATE_ERROR;
- }
-
- /* get first element's of the audio sinkbin */
- first_list = g_list_first(element_bucket);
- if (first_list == NULL) {
- wfd_sink_error("failed to get first list of the element_bucket");
- goto CREATE_ERROR;
- }
-
- first_element = (MMWFDSinkGstElement *)first_list->data;
- if (!first_element) {
- wfd_sink_error("failed to get first element of the audio sinkbin");
- goto CREATE_ERROR;
- }
-
- /* get first element's sinkpad for creating ghostpad */
- pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
- if (!pad) {
- wfd_sink_error("failed to get sink pad from element(%s)",
- GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
- goto CREATE_ERROR;
- }
-
- ghostpad = gst_ghost_pad_new("sink", pad);
- if (!ghostpad) {
- wfd_sink_error("failed to create ghostpad of audio sinkbin");
- goto CREATE_ERROR;
- }
-
- if (FALSE == gst_element_add_pad(a_sinkbin[WFD_SINK_A_S_BIN].gst, ghostpad)) {
- wfd_sink_error("failed to add ghostpad to audio sinkbin");
- goto CREATE_ERROR;
- }
- gst_object_unref(GST_OBJECT(pad));
-
- g_list_free(element_bucket);
-
- /* take it */
- wfd_sink->pipeline->a_sinkbin = a_sinkbin;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
-CREATE_ERROR:
- wfd_sink_error("failed to create audio sinkbin, releasing all");
-
- if (pad)
- gst_object_unref(GST_OBJECT(pad));
- pad = NULL;
-
- if (ghostpad)
- gst_object_unref(GST_OBJECT(ghostpad));
- ghostpad = NULL;
-
- if (element_bucket)
- g_list_free(element_bucket);
- element_bucket = NULL;
-
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_A_S_NUM; i++) { /* NOTE : skip bin */
- if (a_sinkbin != NULL && a_sinkbin[i].gst) {
- GstObject *parent = NULL;
- parent = gst_element_get_parent(a_sinkbin[i].gst);
-
- if (!parent) {
- gst_object_unref(GST_OBJECT(a_sinkbin[i].gst));
- a_sinkbin[i].gst = NULL;
- } else {
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
-
- /* release audio sinkbin with it's childs */
- if (a_sinkbin != NULL && a_sinkbin[WFD_SINK_A_S_BIN].gst)
- gst_object_unref(GST_OBJECT(a_sinkbin[WFD_SINK_A_S_BIN].gst));
-
- MMWFDSINK_FREEIF(a_sinkbin);
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
-{
- MMWFDSinkGstElement *v_decodebin = NULL;
- MMWFDSinkGstElement *first_element = NULL;
- MMWFDSinkGstElement *last_element = NULL;
- GList *element_bucket = NULL;
- GstPad *sinkpad = NULL;
- GstPad *srcpad = NULL;
- GstPad *ghostpad = NULL;
- GList *first_list = NULL;
- GList *last_list = NULL;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->v_decodebin &&
- wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- if (wfd_sink->video_decodebin_is_linked) {
- wfd_sink_debug("video decodebin is already linked... nothing to do");
- return MM_ERROR_NONE;
- }
-
- /* take video decodebin */
- v_decodebin = wfd_sink->pipeline->v_decodebin;
-
- /* check video queue */
- if (v_decodebin[WFD_SINK_V_D_QUEUE].gst)
- element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_QUEUE]);
-
- /* check video hdcp */
- if (v_decodebin[WFD_SINK_V_D_HDCP].gst)
- element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_HDCP]);
-
- /* check video codec */
- switch (wfd_sink->stream_info.video_stream_info.codec) {
- case MM_WFD_SINK_VIDEO_CODEC_H264:
- if (v_decodebin[WFD_SINK_V_D_PARSE].gst)
- element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_PARSE]);
- if (v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst) {
- GstCaps *caps = NULL;
-
- element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_CAPSSETTER]);
- caps = gst_caps_new_simple("video/x-h264",
- "width", G_TYPE_INT, wfd_sink->stream_info.video_stream_info.width,
- "height", G_TYPE_INT, wfd_sink->stream_info.video_stream_info.height,
- "framerate", GST_TYPE_FRACTION, wfd_sink->stream_info.video_stream_info.frame_rate, 1, NULL);
- g_object_set(G_OBJECT(v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst), "caps", caps, NULL);
- gst_object_unref(GST_OBJECT(caps));
- }
- if (v_decodebin[WFD_SINK_V_D_DEC].gst)
- element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_DEC]);
- break;
-
- default:
- wfd_sink_error("video codec is not decied yet. cannot link video decpdebin...");
- return MM_ERROR_WFD_INTERNAL;
- break;
- }
-
- if (element_bucket == NULL) {
- wfd_sink_error("there are no elements to be linked in the video decodebin, destroy it");
- if (MM_ERROR_NONE != __mm_wfd_sink_destroy_video_decodebin(wfd_sink)) {
- wfd_sink_error("failed to destroy video decodebin");
- goto fail_to_link;
- }
- goto done;
- }
-
- /* adding elements to video decodebin */
- if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(v_decodebin[WFD_SINK_V_D_BIN].gst), element_bucket, FALSE)) {
- wfd_sink_error("failed to add elements to video decodebin");
- goto fail_to_link;
- }
-
- /* linking elements in the bucket by added order. */
- if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
- wfd_sink_error("failed to link elements of the video decodebin");
- goto fail_to_link;
- }
-
- /* get first element's sinkpad for creating ghostpad */
- first_list = g_list_first(element_bucket);
- if (first_list == NULL) {
- wfd_sink_error("failed to get first list of the element_bucket");
- goto fail_to_link;
- }
-
- first_element = (MMWFDSinkGstElement *)first_list->data;
- if (!first_element) {
- wfd_sink_error("failed to get first element of the video decodebin");
- goto fail_to_link;
- }
-
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
- if (!sinkpad) {
- wfd_sink_error("failed to get sink pad from element(%s)",
- GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
- goto fail_to_link;
- }
-
- ghostpad = gst_ghost_pad_new("sink", sinkpad);
- if (!ghostpad) {
- wfd_sink_error("failed to create ghostpad of video decodebin");
- goto fail_to_link;
- }
-
- if (FALSE == gst_element_add_pad(v_decodebin[WFD_SINK_V_D_BIN].gst, ghostpad)) {
- wfd_sink_error("failed to add ghostpad to video decodebin");
- goto fail_to_link;
- }
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
-
-
- /* get last element's src for creating ghostpad */
- last_list = g_list_last(element_bucket);
- if (last_list == NULL) {
- wfd_sink_error("failed to get last list of the element_bucket");
- goto fail_to_link;
- }
-
- last_element = (MMWFDSinkGstElement *)last_list->data;
- if (!last_element) {
- wfd_sink_error("failed to get last element of the video decodebin");
- goto fail_to_link;
- }
-
- srcpad = gst_element_get_static_pad(GST_ELEMENT(last_element->gst), "src");
- if (!srcpad) {
- wfd_sink_error("failed to get src pad from element(%s)",
- GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
- goto fail_to_link;
- }
-
- ghostpad = gst_ghost_pad_new("src", srcpad);
- if (!ghostpad) {
- wfd_sink_error("failed to create ghostpad of video decodebin");
- goto fail_to_link;
- }
-
- if (FALSE == gst_element_add_pad(v_decodebin[WFD_SINK_V_D_BIN].gst, ghostpad)) {
- wfd_sink_error("failed to add ghostpad to video decodebin");
- goto fail_to_link;
- }
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
-
- g_list_free(element_bucket);
-
-done:
- wfd_sink->video_decodebin_is_linked = TRUE;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
- /* ERRORS*/
-fail_to_link:
- if (srcpad != NULL)
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
-
- if (sinkpad != NULL)
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
-
- g_list_free(element_bucket);
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-static int __mm_wfd_sink_prepare_videodec(mm_wfd_sink_t *wfd_sink, GstElement *video_dec)
-{
- wfd_sink_debug_fenter();
-
- /* check video decoder is created */
- wfd_sink_return_val_if_fail(video_dec, MM_ERROR_WFD_INVALID_ARGUMENT);
- wfd_sink_return_val_if_fail(wfd_sink && wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_prepare_videosink(mm_wfd_sink_t *wfd_sink, GstElement *video_sink)
-{
- gboolean visible = TRUE;
- gint surface_type = MM_DISPLAY_SURFACE_OVERLAY;
-
- wfd_sink_debug_fenter();
-
- /* check videosink is created */
- wfd_sink_return_val_if_fail(video_sink, MM_ERROR_WFD_INVALID_ARGUMENT);
- wfd_sink_return_val_if_fail(wfd_sink && wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* update display surface */
- mm_attrs_get_int_by_name(wfd_sink->attrs, "display_surface_type", &surface_type);
- wfd_sink_debug("check display surface type attribute: %d", surface_type);
- mm_attrs_get_int_by_name(wfd_sink->attrs, "display_visible", &visible);
- wfd_sink_debug("check display visible attribute: %d", visible);
-
- /* configuring display */
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_EVAS: {
- void *object = NULL;
- gint scaling = 0;
-
- /* common case if using evas surface */
- mm_attrs_get_data_by_name(wfd_sink->attrs, "display_overlay", &object);
- mm_attrs_get_int_by_name(wfd_sink->attrs, "display_evas_do_scaling", &scaling);
- if (object) {
- wfd_sink_debug("set video param : evas-object %x", object);
- g_object_set(G_OBJECT(video_sink), "evas-object", object, NULL);
- } else {
- wfd_sink_error("no evas object");
- return MM_ERROR_WFD_INTERNAL;
- }
- }
- break;
-
- case MM_DISPLAY_SURFACE_OVERLAY: {
- int wl_window_x = 0;
- int wl_window_y = 0;
- int wl_window_width = 0;
- int wl_window_height = 0;
- unsigned int wl_surface_id = 0;
- struct wl_surface *wl_surface = NULL;
- struct wl_display *wl_display = NULL;
- Ecore_Wl_Window *wl_window = NULL;
- wl_client *wlclient = NULL;
- Evas_Object *obj = NULL;
- void *object = NULL;
- const char *object_type = NULL;
- int ret = 0;
-
- mm_attrs_get_data_by_name(wfd_sink->attrs, "display_overlay", &object);
-
- if (object != NULL) {
- obj = (Evas_Object *)object;
- object_type = evas_object_type_get(obj);
- wfd_sink_debug("window object type : %s", object_type);
-
- /* wayland overlay surface */
- LOGI("Wayland overlay surface type");
- evas_object_geometry_get(obj, &wl_window_x, &wl_window_y, &wl_window_width, &wl_window_height);
-
- wfd_sink_debug ("x[%d] y[%d] width[%d] height[%d]", wl_window_x, wl_window_y,
- wl_window_width, wl_window_height);
-
- wl_window = elm_win_wl_window_get(obj);
- wl_surface = (struct wl_surface *) ecore_wl_window_surface_get(wl_window);
-
- /* get wl_display */
- wl_display = (struct wl_display *) ecore_wl_display_get();
-
- ret = mm_wfd_sink_wlclient_create(&wlclient);
- if ( ret != MM_ERROR_NONE) {
- wfd_sink_error("Wayland client create failure");
- return ret;
- }
-
- if (wl_surface && wl_display){
- wfd_sink_debug ("surface = %p, wl_display = %p", wl_surface, wl_display);
- wl_surface_id = mm_wfd_sink_wlclient_get_wl_window_wl_surface_id (wlclient, wl_surface, wl_display);
- wfd_sink_debug ("wl_surface_id = %d", wl_surface_id);
- }
- if (wlclient) {
- g_free(wlclient);
- wlclient = NULL;
- }
-
- wfd_sink_debug("set video param : surface_id %d", wl_surface_id);
- gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink),
- wl_surface_id);
- /* After setting window handle, set render rectangle */
- gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(video_sink),
- wl_window_x, wl_window_y, wl_window_width, wl_window_height);
- } else {
- wfd_sink_debug ("display object is NULL!");
- return MM_ERROR_WFD_INTERNAL;
- }
- }
- break;
-
- case MM_DISPLAY_SURFACE_NULL: {
- /* do nothing */
- wfd_sink_error("Not Supported Surface.");
- return MM_ERROR_WFD_INTERNAL;
- }
- break;
- default: {
- wfd_sink_error("Not Supported Surface.(default case)");
- return MM_ERROR_WFD_INTERNAL;
- }
- break;
- }
-
- g_object_set(G_OBJECT(video_sink), "qos", FALSE, NULL);
- g_object_set(G_OBJECT(video_sink), "async", wfd_sink->ini.video_sink_async, NULL);
- g_object_set(G_OBJECT(video_sink), "max-lateness", (gint64)wfd_sink->ini.video_sink_max_lateness, NULL);
- g_object_set(G_OBJECT(video_sink), "visible", visible, NULL);
- g_object_set(G_OBJECT(video_sink), "ts-offset", (gint64)(wfd_sink->ini.sink_ts_offset), NULL);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- MMWFDSinkGstElement *v_decodebin = NULL;
- GstObject *parent = NULL;
- int i;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- if (wfd_sink->pipeline &&
- wfd_sink->pipeline->v_decodebin &&
- wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
- v_decodebin = wfd_sink->pipeline->v_decodebin;
- } else {
- wfd_sink_debug("video decodebin is not created, nothing to destroy");
- return MM_ERROR_NONE;
- }
-
-
- parent = gst_element_get_parent(v_decodebin[WFD_SINK_V_D_BIN].gst);
- if (!parent) {
- wfd_sink_debug("video decodebin has no parent.. need to relase by itself");
-
- if (GST_STATE(v_decodebin[WFD_SINK_V_D_BIN].gst) >= GST_STATE_READY) {
- wfd_sink_debug("try to change state of video decodebin to NULL");
- ret = gst_element_set_state(v_decodebin[WFD_SINK_V_D_BIN].gst, GST_STATE_NULL);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- wfd_sink_error("failed to change state of video decodebin to NULL");
- return MM_ERROR_WFD_INTERNAL;
- }
- }
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_V_D_NUM; i++) { /* NOTE : skip bin */
- if (v_decodebin[i].gst) {
- parent = gst_element_get_parent(v_decodebin[i].gst);
- if (!parent) {
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
- ((GObject *) v_decodebin[i].gst)->ref_count);
- gst_object_unref(GST_OBJECT(v_decodebin[i].gst));
- v_decodebin[i].gst = NULL;
- } else {
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
- ((GObject *) v_decodebin[i].gst)->ref_count);
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
- /* release video decodebin with it's childs */
- if (v_decodebin[WFD_SINK_V_D_BIN].gst) {
- gst_object_unref(GST_OBJECT(v_decodebin[WFD_SINK_V_D_BIN].gst));
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[WFD_SINK_V_D_BIN].gst)),
- ((GObject *)v_decodebin[WFD_SINK_V_D_BIN].gst)->ref_count);
- }
- } else {
- wfd_sink_debug("video decodebin has parent(%s), unref it",
- GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
-
- gst_object_unref(GST_OBJECT(parent));
- }
-
- wfd_sink->video_decodebin_is_linked = FALSE;
-
- MMWFDSINK_FREEIF(wfd_sink->pipeline->v_decodebin);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
-{
- MMWFDSinkGstElement *v_decodebin = NULL;
- guint video_codec = WFD_VIDEO_UNKNOWN;
- GList *element_bucket = NULL;
- gboolean link = TRUE;
- gint i = 0;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- if (wfd_sink->pipeline->v_decodebin) {
- wfd_sink_debug("video decodebin is already created... nothing to do");
- return MM_ERROR_NONE;
- }
-
- /* check audio decodebin could be linked now */
- switch (wfd_sink->stream_info.video_stream_info.codec) {
- case MM_WFD_SINK_VIDEO_CODEC_H264:
- video_codec = WFD_VIDEO_H264;
- link = TRUE;
- break;
- case MM_WFD_SINK_VIDEO_CODEC_NONE:
- default:
- wfd_sink_debug("video decodebin could NOT be linked now, just create");
- video_codec = wfd_sink->ini.video_codec;
- link = FALSE;
- break;
- }
-
- /* alloc handles */
- v_decodebin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_V_D_NUM);
- if (!v_decodebin) {
- wfd_sink_error("failed to allocate memory for video decodebin");
- return MM_ERROR_WFD_NO_FREE_SPACE;
- }
-
- memset(v_decodebin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_V_D_NUM);
-
- /* create video decodebin */
- v_decodebin[WFD_SINK_V_D_BIN].id = WFD_SINK_V_D_BIN;
- v_decodebin[WFD_SINK_V_D_BIN].gst = gst_bin_new("video_decodebin");
- if (!v_decodebin[WFD_SINK_V_D_BIN].gst) {
- wfd_sink_error("failed to create video decodebin");
- goto CREATE_ERROR;
- }
-
- /* create queue */
- MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_QUEUE, "queue", "video_queue", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_QUEUE].gst, "sink");
- if (v_decodebin[WFD_SINK_V_D_QUEUE].gst)
- __mm_wfd_sink_prepare_queue(wfd_sink, v_decodebin[WFD_SINK_V_D_QUEUE].gst);
-
- /* create hdcp */
- MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_HDCP, wfd_sink->ini.name_of_video_hdcp, "video_hdcp", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_HDCP].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_HDCP].gst, "src");
-
- if (video_codec & WFD_VIDEO_H264) {
- /* create parser */
- MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_PARSE, wfd_sink->ini.name_of_video_parser, "video_parser", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_PARSE].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_PARSE].gst, "src");
-
- /* create capssetter */
- MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_CAPSSETTER, wfd_sink->ini.name_of_video_capssetter, "video_capssetter", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst, "src");
-
- /* create dec */
- MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_DEC, wfd_sink->ini.name_of_video_decoder, "video_dec", FALSE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_DEC].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_DEC].gst, "src");
- if (v_decodebin[WFD_SINK_V_D_DEC].gst) {
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_videodec(wfd_sink, v_decodebin[WFD_SINK_V_D_DEC].gst)) {
- wfd_sink_error("failed to set video decoder property...");
- goto CREATE_ERROR;
- }
- }
- }
-
- g_list_free(element_bucket);
-
- /* take it */
- wfd_sink->pipeline->v_decodebin = v_decodebin;
-
- /* link video decodebin if video codec is fixed */
- if (link) {
- if (MM_ERROR_NONE != __mm_wfd_sink_link_video_decodebin(wfd_sink)) {
- wfd_sink_error("failed to link video decodebin, destroy video decodebin");
- __mm_wfd_sink_destroy_video_decodebin(wfd_sink);
- return MM_ERROR_WFD_INTERNAL;
- }
- }
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
- /* ERRORS */
-CREATE_ERROR:
- wfd_sink_error("failed to create video decodebin, releasing all");
-
- g_list_free(element_bucket);
-
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_V_D_NUM; i++) { /* NOTE : skip bin */
- if (v_decodebin != NULL && v_decodebin[i].gst) {
- GstObject *parent = NULL;
- parent = gst_element_get_parent(v_decodebin[i].gst);
-
- if (!parent) {
- gst_object_unref(GST_OBJECT(v_decodebin[i].gst));
- v_decodebin[i].gst = NULL;
- } else {
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
-
- /* release video decodebin with it's childs */
- if (v_decodebin != NULL && v_decodebin[WFD_SINK_V_D_BIN].gst)
- gst_object_unref(GST_OBJECT(v_decodebin[WFD_SINK_V_D_BIN].gst));
-
- MMWFDSINK_FREEIF(v_decodebin);
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-static int __mm_wfd_sink_destroy_video_sinkbin(mm_wfd_sink_t *wfd_sink)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- MMWFDSinkGstElement *v_sinkbin = NULL;
- GstObject *parent = NULL;
- int i;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- if (wfd_sink->pipeline &&
- wfd_sink->pipeline->v_sinkbin &&
- wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
- v_sinkbin = wfd_sink->pipeline->v_sinkbin;
- } else {
- wfd_sink_debug("video sinkbin is not created, nothing to destroy");
- return MM_ERROR_NONE;
- }
-
-
- parent = gst_element_get_parent(v_sinkbin[WFD_SINK_V_S_BIN].gst);
- if (!parent) {
- wfd_sink_debug("video sinkbin has no parent.. need to relase by itself");
-
- if (GST_STATE(v_sinkbin[WFD_SINK_V_S_BIN].gst) >= GST_STATE_READY) {
- wfd_sink_debug("try to change state of video sinkbin to NULL");
- ret = gst_element_set_state(v_sinkbin[WFD_SINK_V_S_BIN].gst, GST_STATE_NULL);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- wfd_sink_error("failed to change state of video sinkbin to NULL");
- return MM_ERROR_WFD_INTERNAL;
- }
- }
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_V_S_NUM; i++) { /* NOTE : skip bin */
- if (v_sinkbin[i].gst) {
- parent = gst_element_get_parent(v_sinkbin[i].gst);
- if (!parent) {
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
- ((GObject *) v_sinkbin[i].gst)->ref_count);
- gst_object_unref(GST_OBJECT(v_sinkbin[i].gst));
- v_sinkbin[i].gst = NULL;
- } else {
- wfd_sink_debug("unref %s(current ref %d)",
- GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
- ((GObject *) v_sinkbin[i].gst)->ref_count);
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
- /* release video sinkbin with it's childs */
- if (v_sinkbin[WFD_SINK_V_S_BIN].gst) {
- gst_object_unref(GST_OBJECT(v_sinkbin[WFD_SINK_V_S_BIN].gst));
- }
- } else {
- wfd_sink_debug("video sinkbin has parent(%s), unref it ",
- GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
-
- gst_object_unref(GST_OBJECT(parent));
- }
-
- MMWFDSINK_FREEIF(wfd_sink->pipeline->v_sinkbin);
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
-{
- MMWFDSinkGstElement *first_element = NULL;
- MMWFDSinkGstElement *v_sinkbin = NULL;
- GList *element_bucket = NULL;
- GstPad *pad = NULL;
- GstPad *ghostpad = NULL;
- gint i = 0;
- gint surface_type = MM_DISPLAY_SURFACE_OVERLAY;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* alloc handles */
- v_sinkbin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_V_S_NUM);
- if (!v_sinkbin) {
- wfd_sink_error("failed to allocate memory for video sinkbin");
- return MM_ERROR_WFD_NO_FREE_SPACE;
- }
-
- memset(v_sinkbin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_V_S_NUM);
-
- /* create video sinkbin */
- v_sinkbin[WFD_SINK_V_S_BIN].id = WFD_SINK_V_S_BIN;
- v_sinkbin[WFD_SINK_V_S_BIN].gst = gst_bin_new("video_sinkbin");
- if (!v_sinkbin[WFD_SINK_V_S_BIN].gst) {
- wfd_sink_error("failed to create video sinkbin");
- goto CREATE_ERROR;
- }
-
- /* create convert */
- MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_CONVERT, wfd_sink->ini.name_of_video_converter, "video_convert", TRUE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_CONVERT].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_CONVERT].gst, "src");
-
- /* create filter */
- MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_FILTER, wfd_sink->ini.name_of_video_filter, "video_filter", TRUE);
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_FILTER].gst, "sink");
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_FILTER].gst, "src");
- if (v_sinkbin[WFD_SINK_V_S_FILTER].gst) {
- GstCaps *caps = NULL;
- caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "SN12", NULL);
- g_object_set(G_OBJECT(v_sinkbin[WFD_SINK_V_S_FILTER].gst), "caps", caps, NULL);
- gst_object_unref(GST_OBJECT(caps));
- }
-
- /* create sink */
- mm_attrs_get_int_by_name(wfd_sink->attrs, "display_surface_type", &surface_type);
-
- if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
- MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_SINK, wfd_sink->ini.name_of_video_sink, "video_sink", TRUE);
- } else if (surface_type == MM_DISPLAY_SURFACE_EVAS) {
- MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_SINK, wfd_sink->ini.name_of_video_evas_sink, "video_sink", TRUE);
- } else {
- wfd_sink_error("failed to set video sink....");
- goto CREATE_ERROR;
- }
-
- MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_SINK].gst, "sink");
- if (v_sinkbin[WFD_SINK_V_S_SINK].gst) {
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_videosink(wfd_sink, v_sinkbin[WFD_SINK_V_S_SINK].gst)) {
- wfd_sink_error("failed to set video sink property....");
- goto CREATE_ERROR;
- }
- }
-
- /* adding created elements to video sinkbin */
- if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(v_sinkbin[WFD_SINK_V_S_BIN].gst), element_bucket, FALSE)) {
- wfd_sink_error("failed to add elements to video sinkbin");
- goto CREATE_ERROR;
- }
-
- /* linking elements in the bucket by added order. */
- if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
- wfd_sink_error("failed to link elements of the video sinkbin");
- goto CREATE_ERROR;
- }
-
- /* get first element's sinkpad for creating ghostpad */
- first_element = (MMWFDSinkGstElement *)g_list_nth_data(element_bucket, 0);
- if (!first_element) {
- wfd_sink_error("failed to get first element of the video sinkbin");
- goto CREATE_ERROR;
- }
-
- pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
- if (!pad) {
- wfd_sink_error("failed to get pad from first element(%s) of the video sinkbin",
- GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
- goto CREATE_ERROR;
- }
-
- ghostpad = gst_ghost_pad_new("sink", pad);
- if (!ghostpad) {
- wfd_sink_error("failed to create ghostpad of the video sinkbin");
- goto CREATE_ERROR;
- }
-
- if (FALSE == gst_element_add_pad(v_sinkbin[WFD_SINK_V_S_BIN].gst, ghostpad)) {
- wfd_sink_error("failed to add ghostpad to video sinkbin");
- goto CREATE_ERROR;
- }
-
- gst_object_unref(GST_OBJECT(pad));
-
- g_list_free(element_bucket);
-
-
- /* take it */
- wfd_sink->pipeline->v_sinkbin = v_sinkbin;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-
- /* ERRORS */
-CREATE_ERROR:
- wfd_sink_error("failed to create video sinkbin, releasing all");
-
- if (pad)
- gst_object_unref(GST_OBJECT(pad));
- pad = NULL;
-
- if (ghostpad)
- gst_object_unref(GST_OBJECT(ghostpad));
- ghostpad = NULL;
-
- g_list_free(element_bucket);
-
- /* release element which are not added to bin */
- for (i = 1; i < WFD_SINK_V_S_NUM; i++) { /* NOTE : skip bin */
- if (v_sinkbin != NULL && v_sinkbin[i].gst) {
- GstObject *parent = NULL;
- parent = gst_element_get_parent(v_sinkbin[i].gst);
-
- if (!parent) {
- gst_object_unref(GST_OBJECT(v_sinkbin[i].gst));
- v_sinkbin[i].gst = NULL;
- } else {
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
-
- /* release video sinkbin with it's childs */
- if (v_sinkbin != NULL && v_sinkbin[WFD_SINK_V_S_BIN].gst)
- gst_object_unref(GST_OBJECT(v_sinkbin[WFD_SINK_V_S_BIN].gst));
-
- MMWFDSINK_FREEIF(v_sinkbin);
-
- return MM_ERROR_WFD_INTERNAL;
-}
-
-static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- /* cleanup gst stuffs */
- if (wfd_sink->pipeline) {
- MMWFDSinkGstElement *mainbin = wfd_sink->pipeline->mainbin;
-
- if (mainbin) {
- ret = gst_element_set_state(mainbin[WFD_SINK_M_PIPE].gst, GST_STATE_NULL);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- wfd_sink_error("failed to change state of mainbin to NULL");
- return MM_ERROR_WFD_INTERNAL;
- }
-
- if (MM_ERROR_NONE != __mm_wfd_sink_destroy_video_decodebin(wfd_sink)) {
- wfd_sink_error("failed to destroy video decodebin");
- return MM_ERROR_WFD_INTERNAL;
- }
-
- if (MM_ERROR_NONE != __mm_wfd_sink_destroy_audio_decodebin(wfd_sink)) {
- wfd_sink_error("failed to destroy audio decodebin");
- return MM_ERROR_WFD_INTERNAL;
- }
-
- if (MM_ERROR_NONE != __mm_wfd_sink_destroy_video_sinkbin(wfd_sink)) {
- wfd_sink_error("failed to destroy video sinkbin");
- return MM_ERROR_WFD_INTERNAL;
- }
-
- if (MM_ERROR_NONE != __mm_wfd_sink_destroy_audio_sinkbin(wfd_sink)) {
- wfd_sink_error("failed to destroy audio sinkbin");
- return MM_ERROR_WFD_INTERNAL;
- }
-
- gst_object_unref(GST_OBJECT(mainbin[WFD_SINK_M_PIPE].gst));
-
- MMWFDSINK_FREEIF(mainbin);
- }
-
- MMWFDSINK_FREEIF(wfd_sink->pipeline);
- }
-
- wfd_sink->audio_decodebin_is_linked = FALSE;
- wfd_sink->video_decodebin_is_linked = FALSE;
- wfd_sink->need_to_reset_basetime = FALSE;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
-
-static void
-__mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink)
-{
- GstIterator *iter = NULL;
- gboolean done = FALSE;
-
- GstElement *item = NULL;
- GstElementFactory *factory = NULL;
-
- GstState state = GST_STATE_VOID_PENDING;
- GstState pending = GST_STATE_VOID_PENDING;
- GstClockTime time = 200 * GST_MSECOND;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_if_fail(wfd_sink &&
- wfd_sink->pipeline &&
- wfd_sink->pipeline->mainbin &&
- wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
-
- iter = gst_bin_iterate_recurse(GST_BIN(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst));
-
- if (iter != NULL) {
- while (!done) {
- switch (gst_iterator_next(iter, (gpointer)&item)) {
- case GST_ITERATOR_OK:
- gst_element_get_state(GST_ELEMENT(item), &state, &pending, time);
-
- factory = gst_element_get_factory(item) ;
- if (factory) {
- wfd_sink_error("%s:%s : From:%s To:%s refcount : %d",
- GST_STR_NULL(GST_OBJECT_NAME(factory)),
- GST_STR_NULL(GST_ELEMENT_NAME(item)),
- gst_element_state_get_name(state),
- gst_element_state_get_name(pending),
- GST_OBJECT_REFCOUNT_VALUE(item));
- }
- gst_object_unref(item);
- break;
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync(iter);
- break;
- case GST_ITERATOR_ERROR:
- done = TRUE;
- break;
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
- default:
- done = TRUE;
- break;
- }
- }
- }
-
- item = GST_ELEMENT_CAST(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
-
- gst_element_get_state(GST_ELEMENT(item), &state, &pending, time);
-
- factory = gst_element_get_factory(item) ;
- if (factory) {
- wfd_sink_error("%s:%s : From:%s To:%s refcount : %d",
- GST_OBJECT_NAME(factory),
- GST_ELEMENT_NAME(item),
- gst_element_state_get_name(state),
- gst_element_state_get_name(pending),
- GST_OBJECT_REFCOUNT_VALUE(item));
- }
-
- if (iter)
- gst_iterator_free(iter);
-
- wfd_sink_debug_fleave();
-
- return;
-}
-
-const gchar * _mm_wfds_sink_get_state_name(MMWFDSinkStateType state)
-{
- switch (state) {
- case MM_WFD_SINK_STATE_NONE:
- return "NONE";
- case MM_WFD_SINK_STATE_NULL:
- return "NULL";
- case MM_WFD_SINK_STATE_PREPARED:
- return "PREPARED";
- case MM_WFD_SINK_STATE_CONNECTED:
- return "CONNECTED";
- case MM_WFD_SINK_STATE_PLAYING:
- return "PLAYING";
- case MM_WFD_SINK_STATE_PAUSED:
- return "PAUSED";
- case MM_WFD_SINK_STATE_DISCONNECTED:
- return "DISCONNECTED";
- default:
- return "INVAID";
- }
-}
-
-static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint *CEA_resolution, guint *VESA_resolution, guint *HH_resolution)
-{
- if (resolution == MM_WFD_SINK_RESOLUTION_UNKNOWN) return;
-
- *CEA_resolution = 0;
- *VESA_resolution = 0;
- *HH_resolution = 0;
-
- if (resolution & MM_WFD_SINK_RESOLUTION_1920x1080_P30)
- *CEA_resolution |= WFD_CEA_1920x1080P30;
-
- if (resolution & MM_WFD_SINK_RESOLUTION_1280x720_P30)
- *CEA_resolution |= WFD_CEA_1280x720P30;
-
- if (resolution & MM_WFD_SINK_RESOLUTION_960x540_P30)
- *HH_resolution |= WFD_HH_960x540P30;
-
- if (resolution & MM_WFD_SINK_RESOLUTION_864x480_P30)
- *HH_resolution |= WFD_HH_864x480P30;
-
- if (resolution & MM_WFD_SINK_RESOLUTION_720x480_P60)
- *CEA_resolution |= WFD_CEA_720x480P60;
-
- if (resolution & MM_WFD_SINK_RESOLUTION_640x480_P60)
- *CEA_resolution |= WFD_CEA_640x480P60;
-
- if (resolution & MM_WFD_SINK_RESOLUTION_640x360_P30)
- *HH_resolution |= WFD_HH_640x360P30;
-}
-
-int _mm_wfd_sink_set_resolution(mm_wfd_sink_t *wfd_sink, MMWFDSinkResolution resolution)
-{
- MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
-
- wfd_sink_debug_fenter();
-
- wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
-
- MMWFDSINK_PRINT_STATE(wfd_sink);
- cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
- if (cur_state != MM_WFD_SINK_STATE_NULL) {
- wfd_sink_error("This function must be called when MM_WFD_SINK_STATE_NULL");
- return MM_ERROR_WFD_INVALID_STATE;
- }
-
- wfd_sink->supportive_resolution = resolution;
-
- wfd_sink_debug_fleave();
-
- return MM_ERROR_NONE;
-}
+++ /dev/null
-/*
- * libmm-wfd
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
- * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "mm_wfd_sink_util.h"
-#include <stdio.h>
-#include <tzplatform_config.h>
-
-#define DUMP_TS_DATA_PATH tzplatform_mkpath(TZ_SYS_VAR, "tmp/")
-
-static GstPadProbeReturn
-_mm_wfd_sink_util_dump(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
-{
- gint8 *data = NULL;
- gint size = 0;
- FILE *f = NULL;
- char buf[256] = {0, };
- char path[256] = {0, };
- GstElement * parent = NULL;
-
- parent = gst_pad_get_parent_element(pad);
- if (parent == NULL) {
- wfd_sink_error("The parent of pad is NULL.");
- return GST_PAD_PROBE_OK;
- }
-
- snprintf(path, sizeof(path), "%s%s_%s.ts", DUMP_TS_DATA_PATH, gst_element_get_name(parent), gst_pad_get_name(pad));
- gst_object_unref(parent);
-
- if (info && info->type & GST_PAD_PROBE_TYPE_BUFFER) {
- GstMapInfo buf_info;
- GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
-
- gst_buffer_map(buffer, &buf_info, GST_MAP_READ);
-
- wfd_sink_debug("got buffer %p with size %d", buffer, buf_info.size);
- data = (gint8 *)(buf_info.data);
- size = buf_info.size;
- f = fopen(path, "a");
- if (f == NULL) {
- strerror_r(errno, buf, sizeof(buf));
- wfd_sink_error("failed to fopen! : %s", buf);
- return GST_PAD_PROBE_OK;
- }
- fwrite(data, size, 1, f);
- fclose(f);
- gst_buffer_unmap(buffer, &buf_info);
- }
-
- return GST_PAD_PROBE_OK;
-}
-
-static GstPadProbeReturn
-_mm_wfd_sink_util_pad_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
-{
- GstElement *parent = NULL;
-
- wfd_sink_return_val_if_fail(info &&
- info->type != GST_PAD_PROBE_TYPE_INVALID,
- GST_PAD_PROBE_DROP);
- wfd_sink_return_val_if_fail(pad, GST_PAD_PROBE_DROP);
-
- parent = (GstElement *)gst_object_get_parent(GST_OBJECT(pad));
- if (!parent) {
- wfd_sink_error("failed to get parent of pad");
- return GST_PAD_PROBE_DROP;
- }
-
- if (info->type & GST_PAD_PROBE_TYPE_BUFFER) {
- GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
- /* show name and timestamp */
- wfd_sink_debug("BUFFER PROBE : %s:%s : %u:%02u:%02u.%09u (%"G_GSSIZE_FORMAT" bytes)\n",
- GST_STR_NULL(GST_ELEMENT_NAME(parent)),
- GST_STR_NULL(GST_PAD_NAME(pad)),
- GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)),
- gst_buffer_get_size(buffer));
- } else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM ||
- info->type & GST_PAD_PROBE_TYPE_EVENT_UPSTREAM ||
- info->type & GST_PAD_PROBE_TYPE_EVENT_FLUSH ||
- info->type & GST_PAD_PROBE_TYPE_EVENT_BOTH) {
- GstEvent *event = gst_pad_probe_info_get_event(info);
-
- /* show name and event type */
- wfd_sink_debug("EVENT PROBE : %s:%s : %s\n",
- GST_STR_NULL(GST_ELEMENT_NAME(parent)),
- GST_STR_NULL(GST_PAD_NAME(pad)),
- GST_EVENT_TYPE_NAME(event));
-
- if (GST_EVENT_TYPE(event) == GST_EVENT_SEGMENT) {
- const GstSegment *segment = NULL;
- gst_event_parse_segment(event, &segment);
- if (segment)
- wfd_sink_debug("NEWSEGMENT : %" GST_TIME_FORMAT
- " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT " \n",
- GST_TIME_ARGS(segment->start), GST_TIME_ARGS(segment->stop),
- GST_TIME_ARGS(segment->time));
- }
- }
-
- if (parent)
- gst_object_unref(parent);
-
- return GST_PAD_PROBE_OK;
-}
-
-void
-mm_wfd_sink_util_add_pad_probe(GstPad *pad, GstElement *element, const gchar *pad_name)
-{
- GstPad *probe_pad = NULL;
-
- if (!pad) {
- if (element && pad_name)
- probe_pad = gst_element_get_static_pad(element, pad_name);
- } else {
- probe_pad = pad;
- gst_object_ref(probe_pad);
- }
-
- if (probe_pad) {
- wfd_sink_debug("add pad(%s) probe", GST_STR_NULL(GST_PAD_NAME(probe_pad)));
- gst_pad_add_probe(probe_pad, GST_PAD_PROBE_TYPE_DATA_BOTH, _mm_wfd_sink_util_pad_probe_cb, (gpointer)NULL, NULL);
- gst_object_unref(probe_pad);
- }
-}
-
-void
-mm_wfd_sink_util_add_pad_probe_for_data_dump(GstElement *element, const gchar *pad_name)
-{
- GstPad *probe_pad = NULL;
-
- if (element && pad_name)
- probe_pad = gst_element_get_static_pad(element, pad_name);
-
- if (probe_pad) {
- wfd_sink_debug("add pad(%s) probe", GST_STR_NULL(GST_PAD_NAME(probe_pad)));
- gst_pad_add_probe(probe_pad, GST_PAD_PROBE_TYPE_BUFFER, _mm_wfd_sink_util_dump, (gpointer)NULL, NULL);
- gst_object_unref(probe_pad);
- }
-}
-
-static GstPadProbeReturn
-_mm_wfd_sink_util_check_first_buffer_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
-{
- GstElement *parent = NULL;
- GstBuffer *buffer = NULL;
- guint *probe_id = (guint *)user_data;
-
- wfd_sink_return_val_if_fail(pad, GST_PAD_PROBE_DROP);
- wfd_sink_return_val_if_fail(info, GST_PAD_PROBE_DROP);
-
- parent = GST_ELEMENT_CAST(gst_object_get_parent(GST_OBJECT(pad)));
- if (parent == NULL) {
- wfd_sink_error("The parent of pad is NULL.");
- return GST_PAD_PROBE_DROP;
- }
-
- buffer = gst_pad_probe_info_get_buffer(info);
-
- wfd_sink_debug("FIRST BUFFER PROBE : %s:%s : %u:%02u:%02u.%09u (%"G_GSSIZE_FORMAT" bytes)\n",
- GST_STR_NULL(GST_ELEMENT_NAME(parent)), GST_STR_NULL(GST_PAD_NAME(pad)),
- GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)), gst_buffer_get_size(buffer));
-
- if (probe_id && *probe_id > 0) {
- wfd_sink_debug("remove buffer probe[%d]\n", *probe_id);
- gst_pad_remove_probe(pad, *probe_id);
-
- MMWFDSINK_FREEIF(probe_id);
- }
-
- if (parent)
- gst_object_unref(parent);
-
- return GST_PAD_PROBE_REMOVE;
-}
-
-void
-mm_wfd_sink_util_add_pad_probe_for_checking_first_buffer(GstPad *pad, GstElement *element, const gchar *pad_name)
-{
- GstPad *probe_pad = NULL;
- guint *probe_id = NULL;
-
- if (!pad) {
- if (element && pad_name)
- probe_pad = gst_element_get_static_pad(element, pad_name);
- } else {
- probe_pad = pad;
- gst_object_ref(probe_pad);
- }
-
- if (probe_pad) {
- probe_id = g_malloc0(sizeof(guint));
- if (!probe_id) {
- wfd_sink_error("failed to allocate memory for probe id\n");
- gst_object_unref(probe_pad);
- return;
- }
-
- *probe_id = gst_pad_add_probe(probe_pad, GST_PAD_PROBE_TYPE_BUFFER, _mm_wfd_sink_util_check_first_buffer_cb, (gpointer)probe_id, NULL);
- wfd_sink_debug("add pad(%s) probe, %d", GST_STR_NULL(GST_PAD_NAME(probe_pad)), *probe_id);
-
- gst_object_unref(probe_pad);
- }
-
- return;
-}
-
+++ /dev/null
-/*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-#include <glib.h>
-#include <string.h>
-#include <mm_error.h>
-#include <wayland-client.h>
-#include <tizen-extension-client-protocol.h>
-
-#include "mm_wfd_sink_dlog.h"
-#include "mm_wfd_sink_wayland.h"
-
-#define goto_if_fail(expr,label) \
-{ \
- if (!(expr)) { \
- wfd_sink_error(" failed [%s]\n", #expr); \
- goto label; \
- } \
-}
-
-void mm_wfd_sink_handle_resource_id(void *data, struct tizen_resource *tizen_resource, uint32_t id)
-{
- unsigned int *wl_surface_id = data;
-
- *wl_surface_id = id;
-
- wfd_sink_debug("[CLIENT] got wl_surface_id(%d) from server\n", id);
-}
-
-static const struct tizen_resource_listener tz_resource_listener =
-{
- mm_wfd_sink_handle_resource_id,
-};
-
-static void
-mm_wfd_sink_handle_global(void *data, struct wl_registry *registry,
- uint32_t name, const char *interface, uint32_t version)
-{
- return_if_fail (data != NULL);
- wl_client *wlclient = data;
-
- if (strcmp(interface, "tizen_surface") == 0)
- {
- wfd_sink_debug("binding tizen_surface");
- wlclient->tz_surface = wl_registry_bind(registry, name, &tizen_surface_interface, version);
- return_if_fail (wlclient->tz_surface != NULL);
- }
-}
-
-static void mm_wfd_sink_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name)
-{
- wfd_sink_debug("wl_registry_handle_global_remove");
-}
-
-static const struct wl_registry_listener registry_listener =
-{
- mm_wfd_sink_handle_global,
- mm_wfd_sink_handle_global_remove
-};
-
-int mm_wfd_sink_wlclient_create (wl_client ** wlclient)
-{
- wl_client *ptr = NULL;
-
- ptr = g_malloc0 (sizeof (wl_client));
- if (!ptr) {
- wfd_sink_error ("Cannot allocate memory for wlclient\n");
- goto ERROR;
- } else {
- *wlclient = ptr;
- wfd_sink_debug ("Success create wlclient(%p)", *wlclient);
- }
- return MM_ERROR_NONE;
-
-ERROR:
- *wlclient = NULL;
- return MM_ERROR_WFD_NO_FREE_SPACE;
-}
-
-
-int mm_wfd_sink_wlclient_get_wl_window_wl_surface_id (wl_client * wlclient, struct wl_surface *surface, struct wl_display *display)
-{
- goto_if_fail (wlclient != NULL, failed);
- goto_if_fail (surface != NULL, failed);
- goto_if_fail (display != NULL, failed);
-
- unsigned int wl_surface_id = 0;
-
- wlclient->display = display;
- goto_if_fail (wlclient->display != NULL, failed);
-
- wlclient->registry = wl_display_get_registry(wlclient->display);
- goto_if_fail (wlclient->registry != NULL, failed);
-
- wl_registry_add_listener(wlclient->registry, ®istry_listener, wlclient);
- wl_display_dispatch(wlclient->display);
- wl_display_roundtrip(wlclient->display);
-
- /* check global objects */
- goto_if_fail (wlclient->tz_surface != NULL, failed);
-
- /* Get wl_surface_id which is unique in a entire systemw. */
- wlclient->tz_resource = tizen_surface_get_tizen_resource(wlclient->tz_surface, surface);
- goto_if_fail (wlclient->tz_resource != NULL, failed);
-
- tizen_resource_add_listener(wlclient->tz_resource, &tz_resource_listener, &wl_surface_id);
- wl_display_roundtrip(wlclient->display);
- goto_if_fail (wl_surface_id > 0, failed);
-
- mm_wfd_sink_wlclient_finalize(wlclient);
-
- return wl_surface_id;
-
-failed:
- wfd_sink_error ("Failed to get wl_surface_id");
-
- return 0;
-}
-
-void mm_wfd_sink_wlclient_finalize (wl_client * wlclient)
-{
- wfd_sink_debug ("start finalize wlclient");
- return_if_fail (wlclient != NULL)
-
- if (wlclient->tz_surface)
- tizen_surface_destroy(wlclient->tz_surface);
-
- if (wlclient->tz_resource)
- tizen_resource_destroy(wlclient->tz_resource);
-
- /* destroy registry */
- if (wlclient->registry)
- wl_registry_destroy(wlclient->registry);
- return;
-}
--- /dev/null
+lib_LTLIBRARIES = libmmfwfdsink.la
+
+includelibmmfwfdsinkdir = $(includedir)/mmf
+
+includelibmmfwfdsink_HEADERS = include/mm_wfd_sink.h \
+ include/mm_wfd_sink_ini.h \
+ include/mm_wfd_sink_priv.h \
+ include/mm_wfd_sink_dlog.h \
+ include/mm_wfd_sink_attrs.h \
+ include/mm_wfd_sink_util.h
+
+libmmfwfdsink_la_SOURCES = mm_wfd_sink_attrs.c \
+ mm_wfd_sink_ini.c \
+ mm_wfd_sink_util.c \
+ mm_wfd_sink.c \
+ mm_wfd_sink_manager.c \
+ mm_wfd_sink_priv.c \
+ mm_wfd_sink_wayland.c
+
+
+libmmfwfdsink_la_CFLAGS = -I$(srcdir)/include \
+ $(MMCOMMON_CFLAGS) \
+ $(GST_CFLAGS) \
+ $(EVAS_CFLAGS) \
+ $(ELEMENTARY_CFLAGS) \
+ $(GST_PLUGINS_BASE_CFLAGS) \
+ $(GST_VIDEO_CFLAGS) \
+ $(TZPLATFORM_CONFIG_CFLAGS) \
+ $(AUDIOSESSIONMGR_CFLAGS)
+
+libmmfwfdsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+noinst_HEADERS = include/mm_wfd_sink_manager.h \
+ include/mm_wfd_sink_wayland.h \
+ include/mm_wfd_sink_enum.h
+
+libmmfwfdsink_la_LIBADD = $(GST_LIBS) \
+ $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(ELEMENTARY_LIBS) \
+ $(EVAS_LIBS) \
+ $(MMCOMMON_LIBS) \
+ $(AUDIOSESSIONMGR_LIBS) \
+ $(TZPLATFORM_CONFIG_LIBS) \
+ $(GST_VIDEO_LIBS)
+
+libmmfwfdsink_la_CFLAGS += $(MMLOG_CFLAGS) -DMMF_LOG_OWNER=0x02000000 -DMMF_DEBUG_PREFIX=\"MMF-WFD-SINK\"
+libmmfwfdsink_la_LIBADD += $(MMLOG_LIBS)
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _MM_WFD_SINK_H_
+#define _MM_WFD_SINK_H_
+
+#include <string.h>
+#include <glib.h>
+#include <mm_message.h>
+#include <mm_error.h>
+#include <mm_types.h>
+
+/**
+ * * Enumerations of wifi-display sink state.
+ * */
+typedef enum {
+ MM_WFD_SINK_STATE_NONE, /**< wifi-display is not created */
+ MM_WFD_SINK_STATE_NULL, /**< wifi-display is created */
+ MM_WFD_SINK_STATE_PREPARED, /**< wifi-display is prepared */
+ MM_WFD_SINK_STATE_CONNECTED, /**< wifi-display is connected */
+ MM_WFD_SINK_STATE_PLAYING, /**< wifi-display is now playing */
+ MM_WFD_SINK_STATE_PAUSED, /**< wifi-display is now paused */
+ MM_WFD_SINK_STATE_DISCONNECTED, /**< wifi-display is disconnected */
+ MM_WFD_SINK_STATE_NUM, /**< Number of wifi-display states */
+} MMWFDSinkStateType;
+
+/* audio codec : AAC, AC3, LPCM */
+typedef enum {
+ MM_WFD_SINK_AUDIO_CODEC_NONE,
+ MM_WFD_SINK_AUDIO_CODEC_AAC = 0x0F,
+ MM_WFD_SINK_AUDIO_CODEC_AC3 = 0x81,
+ MM_WFD_SINK_AUDIO_CODEC_LPCM = 0x83
+} MMWFDSinkAudioCodec;
+
+/* video codec : H264 */
+typedef enum {
+ MM_WFD_SINK_VIDEO_CODEC_NONE,
+ MM_WFD_SINK_VIDEO_CODEC_H264 = 0x1b
+} MMWFDSinkVideoCodec;
+
+typedef void(*MMWFDMessageCallback)(int error_type, MMWFDSinkStateType state_type, void *user_data);
+
+/**
+ * This function creates a wi-fi display sink object. \n
+ * The attributes of wi-fi display sink are created to get/set some values with application. \n
+ * And, mutex, gstreamer and other resources are initialized at this time. \n
+ * If wi-fi display sink is created, he state will become MM_WFD_SINK_STATE_NULL.. \n
+ *
+ * @param wfd_sink [out] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code. \n
+ * Please refer 'mm_error.h' to know it in detail.
+ * @pre None
+ * @post MM_WFD_SINK_STATE_NULL
+ * @see mm_wfd_sink_destroy
+ * @remark You can create multiple handles on a context at the same time. \n
+ * However, wi-fi display sink cannot guarantee proper operation because of limitation of resources, \n
+ * such as audio device or display device.
+ *
+ * @par Example
+ * @code
+if (mm_wfd_sink_create(&g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to create wi-fi display sink\n");
+}
+
+mm_wfd_sink_set_message_callback(g_wfd_sink, msg_callback, (void*)g_wfd_sink);
+ * @endcode
+ */
+int mm_wfd_sink_create(MMHandleType *wfd_sink);
+
+/**
+ * This function trys to make gstreamer pipeline. \n
+ * If wi-fi display sink is realized, the state will become MM_WFD_SINK_STATE_READY.. \n
+ *
+ * @param wfd_sink [out] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code. \n
+ * Please refer 'mm_error.h' to know it in detail.
+ * @pre MM_WFD_SINK_STATE_NULL
+ * @post MM_WFD_SINK_STATE_PREPARED
+ * @see mm_wfd_sink_unprepare
+ * @remark None
+ * @par Example
+ * @code
+if (mm_wfd_sink_prepare(&g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to realize wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_prepare(MMHandleType wfd_sink);
+
+/**
+ * This function connect wi-fi display source using uri. \n
+ * audio type(AC3 AAC, LPCM) is decided at this time. \n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param uri [in] URI of wi-fi displaysource to be connected
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ *
+ * @pre wi-fi display sink state should be MM_WFD_SINK_STATE_PREPARED
+ * @post wi-fi display sink state will be MM_WFD_SINK_STATE_CONNECTED with no preroll.
+ * @remark None
+ * @par Example
+ * @code
+if (mm_wfd_sink_connect(g_wfd_sink, g_uri) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to connect to wi-fi display source\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_connect(MMHandleType wfd_sink, const char *uri);
+
+/**
+ * This function is to start playing. \n
+ * Data from wi-fi display source will be received. \n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @remark
+ *
+ * @pre wi-fi display sink state may be MM_WFD_SINK_STATE_CONNECTED.
+ * @post wi-fi display sink state will be MM_WFD_SINK_STATE_PLAYING.
+ * @see mm_wfd_sink_disconnect
+ * @remark None
+ * @par Example
+ * @code
+if (mm_wfd_sink_start(g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to start wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_start(MMHandleType wfd_sink);
+
+/**
+ * This function is to pause playing. \n
+ * The wi-fi display sink pause the current stream being received form wi-fi display source. \n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @remark
+ *
+ * @pre wi-fi display sink state should be MM_WFD_SINK_STATE_PLAYING.
+ * @post wi-fi display sink state will be MM_WFD_SINK_STATE_PAUSED.
+ * @see mm_wfd_sink_pause
+ * @remark None
+ * @par Example
+ * @code
+if (mm_wfd_sink_pause(g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to pause wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_pause(MMHandleType wfd_sink);
+
+/**
+ * This function is to resume playing. \n
+ * Data from wi-fi display source will be received. \n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @remark
+ *
+ * @pre wi-fi display sink state may be MM_WFD_SINK_STATE_PAUSED.
+ * @post wi-fi display sink state will be MM_WFD_SINK_STATE_PLAYING.
+ * @see mm_wfd_sink_disconnect
+ * @remark None
+ * @par Example
+ * @code
+if (mm_wfd_sink_start(g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to resume wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_resume(MMHandleType wfd_sink);
+
+/**
+ * This function is to stop playing wi-fi display. \n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ *
+ * @pre wi-fi display sink state may be MM_WFD_SINK_STATE_PLAYING.
+ * @post wi-fi display sink state will be MM_WFD_SINK_STATE_DISCONNECTED.
+ * @see mm_wfd_sink_start
+ * @remark None
+ * @par Example
+ * @code
+if (mm_wfd_sink_disconnect(g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to stop wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_disconnect(MMHandleType wfd_sink);
+
+/**
+ * This function trys to destroy gstreamer pipeline. \n
+ *
+ * @param wfd_sink [out] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code. \n
+ * Please refer 'mm_error.h' to know it in detail.
+ * @pre wi-fi display sink state may be MM_WFD_SINK_STATE_PREPARED or MM_WFD_SINK_STATE_DISCONNECTED.
+ * But, it can be called in any state.
+ * @post MM_WFD_SINK_STATE_NULL
+ * @see mm_wfd_sink_prepare
+ * @remark None
+ * @par Example
+ * @code
+if (mm_wfd_sink_unprepare(&g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to unprepare wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_unprepare(MMHandleType wfd_sink);
+
+/**
+ * This function releases wi-fi display sink object and all resources which were created by mm_wfd_sink_create(). \n
+ * And, wi-fi display sink handle will also be destroyed. \n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state may be MM_WFD_SINK_STATE_NULL. \n
+ * But, it can be called in any state.
+ * @post Because handle is released, there is no any state.
+ * @see mm_wfd_sink_create
+ * @remark This method can be called with a valid wi-fi display sink handle from any state to \n
+ * completely shutdown the wi-fi display sink operation.
+ *
+ * @par Example
+ * @code
+if (mm_wfd_sink_destroy(g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to destroy wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_destroy(MMHandleType wfd_sink);
+
+/**
+ * This function sets callback function for receiving messages from wi-fi display sink. \n
+ * So, player can notify warning, error and normal cases to application. \n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param callback [in] Message callback function.
+ * @param user_param [in] User parameter which is passed to callback function.
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @see MMWFDMessageCallback
+ * @remark None
+ * @par Example
+ * @code
+
+int msg_callback(int error_type, MMWFDSinkStateType state_type, void *user_data)
+{
+ switch (state_type)
+ {
+ case MM_WFD_SINK_STATE_NULL:
+ //do something
+ break;
+
+ case MM_WFD_SINK_STATE_PREPARED:
+ //do something
+ break;
+
+ case MM_WFD_SINK_STATE_CONNECTED:
+ //do something
+ break;
+
+ case MM_WFD_SINK_STATE_PLAYING:
+ //do something
+ break;
+
+ case MM_WFD_SINK_STATE_PAUSED:
+ //do something
+ break;
+
+ case MM_WFD_SINK_DISCONNECTED:
+ //do something
+ break;
+
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+mm_wfd_sink_set_message_callback(g_wfd_sink, msg_callback, (void*)g_wfd_sink);
+ * @endcode
+ */
+int mm_wfd_sink_set_message_callback(MMHandleType wfd_sink, MMWFDMessageCallback callback, void *user_param);
+
+int mm_wfd_sink_set_attribute(MMHandleType wfd_sink, char **err_attr_name, const char *first_attribute_name, ...);
+
+/**
+ * This function get resources \n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state should be MM_WFD_SINK_STATE_READY or MM_WFD_SINK_STATE_PREPARED. \n
+ * @post N/A
+ * @remark resources are released when mm_wfd_sink_destory is called
+ *
+ * @par Example
+ * @code
+if (mm_wfd_sink_get_resource(g_wfd_sink) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to get resources for wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_get_resource(MMHandleType wfd_sink);
+
+/**
+ * This function sets the display surface type for wi-fi display sink\n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param display_surface_type [in] Display surface type
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
+ *
+ * @par Example
+ * @code
+if (mm_wfd_sink_set_display_surface_type(g_wfd_sink, g_display_surface_type) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to set display surface type for wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_set_display_surface_type(MMHandleType wfd_sink, gint display_surface_type);
+
+/**
+ * This function sets the display overlay for wi-fi display sink\n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param display_overlay [in] Display overlay
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
+ *
+ * @par Example
+ * @code
+if (mm_wfd_sink_set_display_overlay(g_wfd_sink, g_display_overlay) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to set display overlay for wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_set_display_overlay(MMHandleType wfd_sink, void *display_overlay);
+
+/**
+ * This function sets the display method for wi-fi display sink\n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param display_method [in] Display method
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
+ *
+ * @par Example
+ * @code
+if (mm_wfd_sink_set_display_method(g_wfd_sink, g_display_method) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to set display method for wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_set_display_method(MMHandleType wfd_sink, gint display_method);
+
+/**
+ * This function sets the display visible for wi-fi display sink\n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param display_visible [in] Display visible
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
+ *
+ * @par Example
+ * @code
+if (mm_wfd_sink_set_display_visible(g_wfd_sink, g_display_visible) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to set display visible for wi-fi display sink\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_set_display_visible(MMHandleType wfd_sink, gint display_visible);
+
+/**
+ * This function gets the width and height of video which is played by wi-fi display sink\n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param width [in] Width of video
+ * @param height [in] Height of video
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state should be MM_WFD_SINK_STATE_CONNECTED or MM_WFD_SINK_STATE_PLAYING. \n
+ *
+ * @par Example
+ * @code
+gint g_width=0, g_height=0;
+
+if (mm_wfd_sink_get_video_resolution(g_wfd_sink, &g_width, &g_height) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to get video resolution.\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_get_video_resolution(MMHandleType wfd_sink, gint *width, gint *height);
+
+/**
+ * This function gets the width and height of video which is played by wi-fi display sink\n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param framerate [in] Framerate of video
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state should be MM_WFD_SINK_STATE_CONNECTED or MM_WFD_SINK_STATE_PLAYING. \n
+ *
+ * @par Example
+ * @code
+gint g_framerate=0;
+
+if (mm_wfd_sink_get_video_framerate(g_wfd_sink, &g_framerate) != MM_ERROR_NONE)
+{
+ wfd_sink_error("failed to get video framerate.\n");
+}
+ * @endcode
+ */
+int mm_wfd_sink_get_video_framerate(MMHandleType wfd_sink, gint *framerate);
+
+/**
+ * This function sets the resolutions for wi-fi display sink\n
+ *
+ * @param wfd_sink [in] Handle of wi-fi display sink
+ * @param resolution [in] Resolutions for wi-fi display sink
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @pre wi-fi display state should be MM_WFD_SINK_STATE_NULL. \n
+ *
+ */
+int mm_wfd_sink_set_resolution(MMHandleType wfd_sink, gint resolution);
+
+int mm_wfd_sink_get_negotiated_video_codec(MMHandleType wfd_sink, gint *codec);
+int mm_wfd_sink_get_negotiated_video_resolution(MMHandleType wfd_sink, gint *width, gint *height);
+int mm_wfd_sink_get_negotiated_video_frame_rate(MMHandleType wfd_sink, gint *frame_rate);
+int mm_wfd_sink_get_negotiated_audio_codec(MMHandleType wfd_sink, gint *codec);
+int mm_wfd_sink_get_negotiated_audio_channel(MMHandleType wfd_sink, gint *channel);
+int mm_wfd_sink_get_negotiated_audio_sample_rate(MMHandleType wfd_sink, gint *sample_rate);
+int mm_wfd_sink_get_negotiated_audio_bitwidth(MMHandleType wfd_sink, gint *bitwidth);
+#endif
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_WFD_ATTRS_H__
+#define __MM_WFD_ATTRS_H__
+
+#include <string.h>
+#include <glib.h>
+#include <mm_message.h>
+#include <mm_error.h>
+#include <mm_types.h>
+#include <mm_attrs_private.h>
+#include <mm_attrs.h>
+#include <mm_debug.h>
+
+/* general */
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+#define MMWFD_MAX_INT (2147483647)
+
+/**
+ * Enumeration for attribute values types.
+ */
+typedef enum {
+ MM_WFD_ATTRS_TYPE_INVALID = -1, /**< Type is invalid */
+ MM_WFD_ATTRS_TYPE_INT, /**< Integer type */
+ MM_WFD_ATTRS_TYPE_DOUBLE, /**< Double type */
+ MM_WFD_ATTRS_TYPE_STRING, /**< UTF-8 String type */
+ MM_WFD_ATTRS_TYPE_DATA, /**< Pointer type */
+ MM_WFD_ATTRS_TYPE_ARRAY, /**< Array type */
+ MM_WFD_ATTRS_TYPE_RANGE, /**< Range type */
+ MM_WFD_ATTRS_TYPE_NUM, /**< Number of attribute type */
+} MMWfdAttrsType;
+
+/**
+ * Enumeration for attribute validation type.
+ */
+typedef enum {
+ MM_WFD_ATTRS_VALID_TYPE_INVALID = -1, /**< Invalid validation type */
+ MM_WFD_ATTRS_VALID_TYPE_NONE, /**< Do not check validity */
+ MM_WFD_ATTRS_VALID_TYPE_INT_ARRAY, /**< validity checking type of integer array */
+ MM_WFD_ATTRS_VALID_TYPE_INT_RANGE, /**< validity checking type of integer range */
+ MM_WFD_ATTRS_VALID_TYPE_DOUBLE_ARRAY, /**< validity checking type of double array */
+ MM_WFD_ATTRS_VALID_TYPE_DOUBLE_RANGE, /**< validity checking type of double range */
+} MMWfdAttrsValidType;
+
+/**
+ * Enumeration for attribute access flag.
+ */
+typedef enum {
+ MM_WFD_ATTRS_FLAG_NONE = 0, /**< None flag is set */
+ MM_WFD_ATTRS_FLAG_READABLE = 1 << 0, /**< Readable */
+ MM_WFD_ATTRS_FLAG_WRITABLE = 1 << 1, /**< Writable */
+ MM_WFD_ATTRS_FLAG_MODIFIED = 1 << 2, /**< Modified */
+
+ MM_WFD_ATTRS_FLAG_RW = MM_WFD_ATTRS_FLAG_READABLE | MM_WFD_ATTRS_FLAG_WRITABLE, /**< Readable and Writable */
+} MMWfdAttrsFlag;
+
+/**
+ * Attribute validity structure
+ */
+typedef struct {
+ MMWfdAttrsType type;
+ MMWfdAttrsValidType validity_type;
+ MMWfdAttrsFlag flag;
+ /**
+ * a union that describes validity of the attribute.
+ * Only when type is 'MM_ATTRS_TYPE_INT' or 'MM_ATTRS_TYPE_DOUBLE',
+ * the attribute can have validity.
+ */
+ union {
+ /**
+ * Validity structure for integer array.
+ */
+ struct {
+ int *array; /**< a pointer of array */
+ int count; /**< size of array */
+ int d_val;
+ } int_array;
+ /**
+ * Validity structure for integer range.
+ */
+ struct {
+ int min; /**< minimum range */
+ int max; /**< maximum range */
+ int d_val;
+ } int_range;
+ /**
+ * Validity structure for double array.
+ */
+ struct {
+ double *array; /**< a pointer of array */
+ int count; /**< size of array */
+ double d_val;
+ } double_array;
+ /**
+ * Validity structure for double range.
+ */
+ struct {
+ double min; /**< minimum range */
+ double max; /**< maximum range */
+ double d_val;
+ } double_range;
+ };
+} MMWfdAttrsInfo;
+
+MMHandleType _mmwfd_construct_attribute(MMHandleType hwfd);
+void _mmwfd_deconstruct_attribute(MMHandleType hwfd);
+int _mmwfd_set_attribute(MMHandleType hwfd, char **err_atr_name, const char *attribute_name, va_list args_list);
+int _mmwfd_get_attributes_info(MMHandleType handle, const char *attribute_name, MMWfdAttrsInfo *dst_info);
+int _mmwfd_get_attribute(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list args_list);
+#endif /* __MM_WFD_ATTRS_H__ */
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __MM_WFD_SINK_DLOG_H__
+#define __MM_WFD_SINK_DLOG_H__
+
+#include <dlog.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "MM_WFD_SINK"
+
+#define FONT_COLOR_RESET "\033[0m"
+#define FONT_COLOR_RED "\033[31m"
+#define FONT_COLOR_GREEN "\033[32m"
+#define FONT_COLOR_YELLOW "\033[33m"
+#define FONT_COLOR_BLUE "\033[34m"
+#define FONT_COLOR_PURPLE "\033[35m"
+#define FONT_COLOR_CYAN "\033[36m"
+#define FONT_COLOR_GRAY "\033[37m"
+
+#define wfd_sink_debug(fmt, arg...) do { \
+ LOGD(FONT_COLOR_RESET""fmt"", ##arg); \
+ } while (0)
+
+#define wfd_sink_info(fmt, arg...) do { \
+ LOGI(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
+ } while (0)
+
+#define wfd_sink_error(fmt, arg...) do { \
+ LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+ } while (0)
+
+#define wfd_sink_warning(fmt, arg...) do { \
+ LOGW(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg); \
+ } while (0)
+
+#define wfd_sink_debug_fenter() do { \
+ LOGD(FONT_COLOR_RESET"<Enter>"); \
+ } while (0)
+
+#define wfd_sink_debug_fleave() do { \
+ LOGD(FONT_COLOR_RESET"<Leave>"); \
+ } while (0)
+
+#define wfd_sink_error_fenter() do { \
+ LOGE(FONT_COLOR_RED"NO-ERROR : <Enter>"FONT_COLOR_RESET); \
+ } while (0)
+
+#define wfd_sink_error_fleave() do { \
+ LOGE(FONT_COLOR_RED"NO-ERROR : <Leave>"FONT_COLOR_RESET); \
+ } while (0)
+
+#define wfd_sink_sucure_info(fmt, arg...) do { \
+ SECURE_LOGI(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
+ } while (0)
+
+#define wfd_sink_return_if_fail(expr) \
+ if(!(expr)) { \
+ wfd_sink_error(FONT_COLOR_RED"failed [%s]\n"FONT_COLOR_RESET, #expr); \
+ return; \
+ }
+
+#define wfd_sink_return_val_if_fail(expr, val) \
+ if (!(expr)) { \
+ wfd_sink_error(FONT_COLOR_RED"failed [%s]\n"FONT_COLOR_RESET, #expr); \
+ return val; \
+ }
+
+#define wfd_sink_assert_not_reached() \
+ { \
+ wfd_sink_error(FONT_COLOR_RED"assert_not_reached()"FONT_COLOR_RESET); \
+ assert(0); \
+ }
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MM_WFD_SINK_DLOG_H__ */
+
--- /dev/null
+/*
+ * Enumeration for WFD
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _MM_WFD_SINK_WFD_ENUM_H_
+#define _MM_WFD_SINK_WFD_ENUM_H_
+
+typedef enum {
+ WFD_AUDIO_UNKNOWN = 0,
+ WFD_AUDIO_LPCM = (1 << 0),
+ WFD_AUDIO_AAC = (1 << 1),
+ WFD_AUDIO_AC3 = (1 << 2)
+} WFDAudioFormats;
+
+typedef enum {
+ WFD_FREQ_UNKNOWN = 0,
+ WFD_FREQ_44100 = (1 << 0),
+ WFD_FREQ_48000 = (1 << 1)
+} WFDAudioFreq;
+
+typedef enum {
+ WFD_CHANNEL_UNKNOWN = 0,
+ WFD_CHANNEL_2 = (1 << 0),
+ WFD_CHANNEL_4 = (1 << 1),
+ WFD_CHANNEL_6 = (1 << 2),
+ WFD_CHANNEL_8 = (1 << 3)
+} WFDAudioChannels;
+
+
+typedef enum {
+ WFD_VIDEO_UNKNOWN = 0,
+ WFD_VIDEO_H264 = (1 << 0)
+} WFDVideoCodecs;
+
+typedef enum {
+ WFD_VIDEO_CEA_RESOLUTION = 0,
+ WFD_VIDEO_VESA_RESOLUTION,
+ WFD_VIDEO_HH_RESOLUTION
+} WFDVideoNativeResolution;
+
+typedef enum {
+ WFD_CEA_UNKNOWN = 0,
+ WFD_CEA_640x480P60 = (1 << 0),
+ WFD_CEA_720x480P60 = (1 << 1),
+ WFD_CEA_720x480I60 = (1 << 2),
+ WFD_CEA_720x576P50 = (1 << 3),
+ WFD_CEA_720x576I50 = (1 << 4),
+ WFD_CEA_1280x720P30 = (1 << 5),
+ WFD_CEA_1280x720P60 = (1 << 6),
+ WFD_CEA_1920x1080P30 = (1 << 7),
+ WFD_CEA_1920x1080P60 = (1 << 8),
+ WFD_CEA_1920x1080I60 = (1 << 9),
+ WFD_CEA_1280x720P25 = (1 << 10),
+ WFD_CEA_1280x720P50 = (1 << 11),
+ WFD_CEA_1920x1080P25 = (1 << 12),
+ WFD_CEA_1920x1080P50 = (1 << 13),
+ WFD_CEA_1920x1080I50 = (1 << 14),
+ WFD_CEA_1280x720P24 = (1 << 15),
+ WFD_CEA_1920x1080P24 = (1 << 16)
+} WFDVideoCEAResolution;
+
+typedef enum {
+ WFD_VESA_UNKNOWN = 0,
+ WFD_VESA_800x600P30 = (1 << 0),
+ WFD_VESA_800x600P60 = (1 << 1),
+ WFD_VESA_1024x768P30 = (1 << 2),
+ WFD_VESA_1024x768P60 = (1 << 3),
+ WFD_VESA_1152x864P30 = (1 << 4),
+ WFD_VESA_1152x864P60 = (1 << 5),
+ WFD_VESA_1280x768P30 = (1 << 6),
+ WFD_VESA_1280x768P60 = (1 << 7),
+ WFD_VESA_1280x800P30 = (1 << 8),
+ WFD_VESA_1280x800P60 = (1 << 9),
+ WFD_VESA_1360x768P30 = (1 << 10),
+ WFD_VESA_1360x768P60 = (1 << 11),
+ WFD_VESA_1366x768P30 = (1 << 12),
+ WFD_VESA_1366x768P60 = (1 << 13),
+ WFD_VESA_1280x1024P30 = (1 << 14),
+ WFD_VESA_1280x1024P60 = (1 << 15),
+ WFD_VESA_1400x1050P30 = (1 << 16),
+ WFD_VESA_1400x1050P60 = (1 << 17),
+ WFD_VESA_1440x900P30 = (1 << 18),
+ WFD_VESA_1440x900P60 = (1 << 19),
+ WFD_VESA_1600x900P30 = (1 << 20),
+ WFD_VESA_1600x900P60 = (1 << 21),
+ WFD_VESA_1600x1200P30 = (1 << 22),
+ WFD_VESA_1600x1200P60 = (1 << 23),
+ WFD_VESA_1680x1024P30 = (1 << 24),
+ WFD_VESA_1680x1024P60 = (1 << 25),
+ WFD_VESA_1680x1050P30 = (1 << 26),
+ WFD_VESA_1680x1050P60 = (1 << 27),
+ WFD_VESA_1920x1200P30 = (1 << 28),
+ WFD_VESA_1920x1200P60 = (1 << 29)
+} WFDVideoVESAResolution;
+
+typedef enum {
+ WFD_HH_UNKNOWN = 0,
+ WFD_HH_800x480P30 = (1 << 0),
+ WFD_HH_800x480P60 = (1 << 1),
+ WFD_HH_854x480P30 = (1 << 2),
+ WFD_HH_854x480P60 = (1 << 3),
+ WFD_HH_864x480P30 = (1 << 4),
+ WFD_HH_864x480P60 = (1 << 5),
+ WFD_HH_640x360P30 = (1 << 6),
+ WFD_HH_640x360P60 = (1 << 7),
+ WFD_HH_960x540P30 = (1 << 8),
+ WFD_HH_960x540P60 = (1 << 9),
+ WFD_HH_848x480P30 = (1 << 10),
+ WFD_HH_848x480P60 = (1 << 11)
+} WFDVideoHHResolution;
+
+typedef enum {
+ WFD_H264_UNKNOWN_PROFILE = 0,
+ WFD_H264_BASE_PROFILE = (1 << 0),
+ WFD_H264_HIGH_PROFILE = (1 << 1)
+} WFDVideoH264Profile;
+
+typedef enum {
+ WFD_H264_LEVEL_UNKNOWN = 0,
+ WFD_H264_LEVEL_3_1 = (1 << 0),
+ WFD_H264_LEVEL_3_2 = (1 << 1),
+ WFD_H264_LEVEL_4 = (1 << 2),
+ WFD_H264_LEVEL_4_1 = (1 << 3),
+ WFD_H264_LEVEL_4_2 = (1 << 4)
+} WFDVideoH264Level;
+
+#endif /*_MM_WFD_SINK_WFD_ENUM_H_*/
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_WFD_SINK_INI_H__
+#define __MM_WFD_SINK_INI_H__
+
+#include <glib.h>
+#include <tzplatform_config.h>
+#include "mm_wfd_sink_enum.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+enum WFDSinkINIProbeFlags
+{
+ WFD_SINK_INI_PROBE_DEFAULT = 0,
+ WFD_SINK_INI_PROBE_TIMESTAMP = (1 << 0),
+ WFD_SINK_INI_PROBE_BUFFERSIZE = (1 << 1),
+ WFD_SINK_INI_PROBE_CAPS = (1 << 2),
+ WFD_SINK_INI_PROBE_BUFFER_DURATION = (1 << 3),
+};
+
+#define MM_WFD_SINK_INI_DEFAULT_PATH SYSCONFDIR"/multimedia/mmfw_wfd_sink.ini"
+
+#define WFD_SINK_INI_MAX_STRLEN 256
+#define WFD_SINK_INI_MAX_ELEMENT 10
+
+/* NOTE : MMPlayer has no initalizing API for library itself
+ * so we cannot decide when those ini values to be released.
+ * this is the reason of all string items are static array.
+ * make it do with malloc when MMPlayerInitialize() API created
+ * before that time, we should be careful with size limitation
+ * of each string item.
+ */
+typedef struct __mm_wfd_sink_ini {
+ /* general */
+ gchar gst_param[5][WFD_SINK_INI_MAX_STRLEN];
+ gboolean generate_dot;
+ gboolean enable_pad_probe;
+ gint state_change_timeout;
+ gboolean set_debug_property;
+ gboolean enable_asm;
+ gint jitter_buffer_latency;
+ gint video_sink_max_lateness;
+ gint sink_ts_offset;
+ gboolean audio_sink_async;
+ gboolean video_sink_async;
+ gboolean enable_retransmission;
+ gboolean enable_reset_basetime;
+ gboolean enable_ts_data_dump;
+ gboolean enable_wfdsrc_pad_probe;
+
+ /* pipeline */
+ gchar name_of_source[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_tsdemux[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_audio_hdcp[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_aac_parser[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_aac_decoder[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_ac3_parser[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_ac3_decoder[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_lpcm_converter[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_lpcm_filter[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_audio_resampler[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_audio_volume[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_audio_sink[WFD_SINK_INI_MAX_STRLEN];
+
+ gchar name_of_video_hdcp[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_video_parser[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_video_capssetter[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_video_decoder[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_video_converter[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_video_filter[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_video_sink[WFD_SINK_INI_MAX_STRLEN];
+ gchar name_of_video_evas_sink[WFD_SINK_INI_MAX_STRLEN];
+
+ /* audio parameter for reponse of M3 request */
+ guint audio_codec;
+ guint audio_latency;
+ guint audio_channel;
+ guint audio_sampling_frequency;
+
+ /* video parameter for reponse of M3 request */
+ guint video_codec;
+ guint video_native_resolution;
+ guint video_cea_support;
+ guint video_vesa_support;
+ guint video_hh_support;
+ guint video_profile;
+ guint video_level;
+ guint video_latency;
+ gint video_vertical_resolution;
+ gint video_horizontal_resolution;
+ gint video_minimum_slicing;
+ gint video_slice_enc_param;
+ gint video_framerate_control_support;
+
+ /* hdcp parameter for reponse of M3 request */
+ gint hdcp_content_protection;
+ gint hdcp_port_no;
+} mm_wfd_sink_ini_t;
+
+
+/*Default sink ini values*/
+/* General*/
+#define DEFAULT_GST_PARAM ""
+#define DEFAULT_GENERATE_DOT FALSE
+#define DEFAULT_ENABLE_PAD_PROBE FALSE
+#define DEFAULT_STATE_CHANGE_TIMEOUT 5 /* sec */
+#define DEFAULT_SET_DEBUG_PROPERTY TRUE
+#define DEFAULT_ENABLE_ASM FALSE
+#define DEFAULT_JITTER_BUFFER_LATENCY 10 /* msec */
+#define DEFAULT_ENABLE_RETRANSMISSION FALSE
+#define DEFAULT_ENABLE_RESET_BASETIME TRUE
+#define DEFAULT_VIDEO_SINK_MAX_LATENESS 20000000 /* nsec */
+#define DEFAULT_SINK_TS_OFFSET 150000000 /* nsec */
+#define DEFAULT_AUDIO_SINK_ASYNC FALSE
+#define DEFAULT_VIDEO_SINK_ASYNC FALSE
+#define DEFAULT_ENABLE_TS_DATA_DUMP FALSE
+#define DEFAULT_ENABLE_WFDRTSPSRC_PAD_PROBE FALSE
+
+/* Pipeline */
+#define DEFAULT_NAME_OF_SOURCE "wfdsrc"
+#define DEFAULT_NAME_OF_TSDEMUX ""
+#define DEFAULT_NAME_OF_AUDIO_HDCP ""
+#define DEFAULT_NAME_OF_AAC_PARSER ""
+#define DEFAULT_NAME_OF_AAC_DECODER ""
+#define DEFAULT_NAME_OF_AC3_PARSER ""
+#define DEFAULT_NAME_OF_AC3_DECODER ""
+#define DEFAULT_NAME_OF_LPCM_CONVERTER ""
+#define DEFAULT_NAME_OF_LPCM_FILTER ""
+#define DEFAULT_NAME_OF_AUDIO_RESAMPLER ""
+#define DEFAULT_NAME_OF_AUDIO_VOLUME ""
+#define DEFAULT_NAME_OF_AUDIO_SPLITTER ""
+#define DEFAULT_NAME_OF_AUDIO_SINK ""
+#define DEFAULT_NAME_OF_VIDEO_HDCP ""
+#define DEFAULT_NAME_OF_VIDEO_PARSER ""
+#define DEFAULT_NAME_OF_VIDEO_CAPSSETTER ""
+#define DEFAULT_NAME_OF_VIDEO_DECODER ""
+#define DEFAULT_NAME_OF_VIDEO_CONVERTER ""
+#define DEFAULT_NAME_OF_VIDEO_FILTER ""
+#define DEFAULT_NAME_OF_VIDEO_SINK ""
+#define DEFAULT_NAME_OF_EVAS_VIDEO_SINK ""
+
+/* Audio */
+#define DEFAULT_AUDIO_CODEC WFD_AUDIO_LPCM | WFD_AUDIO_AAC
+#define DEFAULT_AUDIO_LATENCY 0x0
+#define DEFAULT_AUDIO_CHANNELS WFD_CHANNEL_2
+#define DEFAULT_AUDIO_SAMP_FREQUENCY WFD_FREQ_44100 | WFD_FREQ_48000
+
+/* Video */
+#define DEFAULT_VIDEO_CODEC WFD_VIDEO_H264
+#define DEFAULT_VIDEO_NATIVE_RESOLUTION 0x20
+/* CEA : WFD_CEA_640x480P60 | WFD_CEA_720x480P60 |WFD_CEA_720x576P50 |WFD_CEA_1280x720P30 |
+ WFD_CEA_1280x720P25 | WFD_CEA_1280x720P24 */
+#define DEFAULT_VIDEO_CEA_SUPPORT 0x84ab
+/* VESA : WFD_VESA_800x600P30 */
+#define DEFAULT_VIDEO_VESA_SUPPORT 0x1
+/* HH : WFD_HH_800x480P30 | WFD_HH_854x480P30 | WFD_HH_864x480P30 | WFD_HH_640x360P30 | WFD_HH_960x540P30 | WFD_HH_848x480P30 */
+#define DEFAULT_VIDEO_HH_SUPPORT 0x555
+#define DEFAULT_VIDEO_PROFILE WFD_H264_BASE_PROFILE
+#define DEFAULT_VIDEO_LEVEL WFD_H264_LEVEL_3_2
+#define DEFAULT_VIDEO_LATENCY 0x0
+#define DEFAULT_VIDEO_VERTICAL_RESOLUTION 720
+#define DEFAULT_VIDEO_HORIZONTAL_RESOLUTION 1280
+#define DEFAULT_VIDEO_MIN_SLICESIZE 0
+#define DEFAULT_VIDEO_SLICE_ENC_PARAM 200
+#define DEFAULT_VIDEO_FRAMERATE_CONTROL 11
+
+/* HDCP */
+#define DEFAULT_HDCP_CONTENT_PROTECTION 0x0
+#define DEFAULT_HDCP_PORT_NO 0
+
+
+#define MM_WFD_SINK_DEFAULT_INI \
+" \
+[general]\n\
+; parameters for initializing gstreamer\n\
+; DEFAULT SET(--gst-debug=2, *wfd*:5)\n\
+gstparam1 = --gst-debug=2, *wfd*:5, *wfdtsdemux:1, *wfdrtpbuffer:1\n\
+gstparam2 =\n\
+gstparam3 =\n\
+gstparam4 =\n\
+gstparam5 =\n\
+\n\
+; generating dot file representing pipeline state\n\
+; do export GST_DEBUG_DUMP_DOT_DIR=[dot file path] in the shell\n\
+generate dot = no\n\
+\n\
+; enable pad probe\n\
+enable pad probe = no\n\
+\n\
+; enable wfdsrc inner pad probe\n\
+enable wfdsrc pad probe = no\n\
+\n\
+; enable ts data dump(eg. /var/tmp/*.ts)\n\
+enable ts data dump = no\n\
+\n\
+; allowed timeout for changing pipeline state\n\
+state change timeout = 5 ; sec\n\
+\n\
+; set debug property to wfdsrc plugin for debugging rtsp message\n\
+set debug property = yes\n\
+\n\
+; for asm function enable = yes, disable = no\n\
+enable asm = no\n\
+\n\
+; 0: default value set by wfdsrc element, other: user define value.\n\
+jitter buffer latency=10\n\
+\n\
+; for retransmission request enable = yes, disable = no\n\
+enable retransmission = no\n\
+\n\
+; for reset basetime, enable = yes, disable = no\n\
+enable reset basetime = yes\n\
+\n\
+; Maximum number of nanoseconds that a buffer can be late before it is dropped by videosink(-1 unlimited)\n\
+video sink max lateness=20000000\n\
+\n\
+; nanoseconds to be added to buffertimestamp by sink elements\n\
+sink ts offset=150000000\n\
+\n\
+; if no, go asynchronously to PAUSED without preroll \n\
+audio sink async=no\n\
+\n\
+; if no, go asynchronously to PAUSED without preroll \n\
+video sink async=no\n\
+\n\
+\n\
+\n\
+[pipeline]\n\
+wfdsrc element = wfdsrc\n\
+\n\
+tsdemux element = wfdtsdemux\n\
+\n\
+aac parser element = aacparse\n\
+\n\
+aac decoder element = avdec_aac\n\
+\n\
+ac3 parser element = ac3parse\n\
+\n\
+ac3 decoder element =\n\
+\n\
+lpcm converter element =\n\
+\n\
+lpcm filter element = capsfilter\n\
+\n\
+audio resampler element = audioconvert\n\
+\n\
+audio volume element =\n\
+\n\
+audio sink element = pulsesink\n\
+\n\
+video parser element = h264parse\n\
+\n\
+video capssetter element = capssetter\n\
+\n\
+video decoder element = avdec_h264;sprddec_h264;omxh264dec\n\
+\n\
+video converter element =\n\
+\n\
+video filter element =\n\
+\n\
+video sink element = waylandsink;xvimagesink\n\
+\n\
+\n\
+\n\
+[audio param]\n\
+; 0x1: LPCM, 0x2: aac, 0x4: ac3\n\
+;default aac and LPCM\n\
+audio codec=0x3\n\
+\n\
+audio latency=0x0\n\
+\n\
+;0x1 : 48000khz, 0x2: 44100khz\n\
+audio sampling frequency=0x3\n\
+\n\
+; 0x1:2 channels, 0x2:4 channels, 0x4:6channels, 0x8:8channels\n\
+audio channels=0x1\n\
+\n\
+\n\
+\n\
+[video param]\n\
+; 0: H264CBP 1: H264CHP\n\
+video codec=0x1\n\
+\n\
+video native resolution = 0x20\n\
+\n\
+video cea support=0x842b\n\
+\n\
+video vesa support=0x1\n\
+\n\
+video hh support=0x555\n\
+\n\
+; 0x1:base, 0x2:high\n\
+video profile=0x1\n\
+\n\
+; 0x1:level_3_1, 0x2:level_3_2, 0x4:level_4, 0x8:level_4_1, 0x10:level_4_2\n\
+video level=0x2\n\
+\n\
+video latency=0x0\n\
+\n\
+video vertical resolution=720\n\
+\n\
+video horizontal resolution=1280\n\
+\n\
+video minimum slicesize=0\n\
+\n\
+video slice encoding params=200\n\
+\n\
+video framerate control support=11\n\
+\n\
+\n\
+\n\
+[hdcp param]\n\
+;0x0:none, 0x1:HDCP_2.0, 0x2:HDCP_2.1\n\
+hdcp content protection=0x0\n\
+\n\
+hdcp port no=0\n\
+\n\
+"
+
+int
+mm_wfd_sink_ini_load(mm_wfd_sink_ini_t *ini);
+
+int
+mm_wfd_sink_ini_unload(mm_wfd_sink_ini_t *ini);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
+ * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_WFD_SINK_MANAGER_H__
+#define __MM_WFD_SINK_MANAGER_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include "mm_wfd_sink_priv.h"
+#include "mm_wfd_sink_util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WFD_SINK_MANAGER_LOCK(wfd_sink) \
+ do {\
+ if (wfd_sink) {\
+ g_mutex_lock(&((wfd_sink)->manager_thread_mutex));\
+ }\
+ } while (0);
+
+#define WFD_SINK_MANAGER_UNLOCK(wfd_sink) \
+ do {\
+ if (wfd_sink) {\
+ g_mutex_unlock(&((wfd_sink)->manager_thread_mutex));\
+ }\
+ } while (0);
+
+#define WFD_SINK_MANAGER_WAIT_CMD(wfd_sink) \
+ do {\
+ if (wfd_sink->manager_thread_exit == FALSE) {\
+ wfd_sink_debug("manager thread is waiting for command signal");\
+ wfd_sink->waiting_cmd = TRUE; \
+ g_cond_wait(&((wfd_sink)->manager_thread_cond), &((wfd_sink)->manager_thread_mutex)); \
+ wfd_sink->waiting_cmd = FALSE; \
+ } else {\
+ wfd_sink_debug("manager thread is stopped, don't need to wait for command signal");\
+ }\
+ } while (0);
+
+#define WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, cmd) \
+ do {\
+ WFD_SINK_MANAGER_LOCK(wfd_sink);\
+ if (cmd == WFD_SINK_MANAGER_CMD_EXIT) {\
+ g_list_free(wfd_sink->manager_thread_cmd);\
+ wfd_sink->manager_thread_cmd = NULL;\
+ wfd_sink->manager_thread_exit = TRUE;\
+ }\
+ wfd_sink->manager_thread_cmd = g_list_append(wfd_sink->manager_thread_cmd, GINT_TO_POINTER(cmd)); \
+ WFD_SINK_MANAGER_UNLOCK(wfd_sink);\
+ } while (0);
+
+#define WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink) \
+ do {\
+ WFD_SINK_MANAGER_LOCK(wfd_sink);\
+ if (wfd_sink->waiting_cmd) {\
+ if (wfd_sink->manager_thread_cmd) {\
+ wfd_sink_debug("send command signal to manager thread");\
+ g_cond_signal(&((wfd_sink)->manager_thread_cond));\
+ }\
+ }\
+ WFD_SINK_MANAGER_UNLOCK(wfd_sink);\
+ } while (0);
+
+/**
+ * This function is to initialize manager
+ *
+ * @param[in] handle Handle of wfd_sink.
+ * @return This function returns zero on success, or negative value with errors.
+ * @remarks
+ * @see
+ *
+ */
+int _mm_wfd_sink_init_manager(mm_wfd_sink_t *wfd_sink);
+/**
+ * This function is to release manager
+ *
+ * @param[in] handle Handle of wfd_sink.
+ * @return This function returns zero on success, or negative value with errors.
+ * @remarks
+ * @see
+ *
+ */
+int _mm_wfd_sink_release_manager(mm_wfd_sink_t *wfd_sink);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _MM_WFD_SINK_PRIV_H_
+#define _MM_WFD_SINK_PRIV_H_
+
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <gst/gst.h>
+#include <mm_types.h>
+#include <mm_attrs.h>
+#include <mm_message.h>
+#include <mm_error.h>
+#include <mm_types.h>
+
+#include "mm_wfd_sink_ini.h"
+#include "mm_wfd_sink_attrs.h"
+#include "mm_wfd_sink.h"
+
+/* main pipeline's element id */
+enum WFDSinkMainElementID {
+ WFD_SINK_M_PIPE = 0, /* NOTE : WFD_SINK_M_PIPE should be zero */
+ WFD_SINK_M_SRC,
+ WFD_SINK_M_DEPAY,
+ WFD_SINK_M_DEMUX,
+ WFD_SINK_M_NUM
+};
+
+/* audio decodebin's element id */
+enum WFDSinkAudioDecodeBinElementID {
+ WFD_SINK_A_D_BIN = 0, /* NOTE : WFD_SINK_A_D_BIN should be zero */
+ WFD_SINK_A_D_QUEUE,
+ WFD_SINK_A_D_HDCP,
+ WFD_SINK_A_D_AAC_PARSE,
+ WFD_SINK_A_D_AAC_DEC,
+ WFD_SINK_A_D_AC3_PARSE,
+ WFD_SINK_A_D_AC3_DEC,
+ WFD_SINK_A_D_LPCM_CONVERTER,
+ WFD_SINK_A_D_LPCM_FILTER,
+ WFD_SINK_A_D_NUM
+};
+
+/* audio sinkbin's element id */
+enum WFDSinkAudioSinkBinElementID {
+ WFD_SINK_A_S_BIN = 0, /* NOTE : WFD_SINK_A_S_BIN should be zero */
+ WFD_SINK_A_S_RESAMPLER,
+ WFD_SINK_A_S_VOLUME,
+ WFD_SINK_A_S_SINK,
+ WFD_SINK_A_S_NUM
+};
+
+/* video decodebin's element id */
+enum WFDSinkVideoDecodeBinElementID {
+ WFD_SINK_V_D_BIN = 0, /* NOTE : WFD_SINK_V_D_BIN should be zero */
+ WFD_SINK_V_D_QUEUE,
+ WFD_SINK_V_D_HDCP,
+ WFD_SINK_V_D_PARSE,
+ WFD_SINK_V_D_CAPSSETTER,
+ WFD_SINK_V_D_DEC,
+ WFD_SINK_V_D_NUM
+};
+
+/* video sinkbin's element id */
+enum WFDSinkVideoSinkBinElementID {
+ WFD_SINK_V_S_BIN = 0, /* NOTE : WFD_SINK_V_S_BIN should be zero */
+ WFD_SINK_V_S_CONVERT,
+ WFD_SINK_V_S_FILTER,
+ WFD_SINK_V_S_SINK,
+ WFD_SINK_V_S_NUM
+};
+
+/**
+ * * Enumerations of wifi-display command.
+ * */
+typedef enum {
+ MM_WFD_SINK_COMMAND_NONE, /**< command for nothing */
+ MM_WFD_SINK_COMMAND_CREATE, /**< command for creating wifi-display sink */
+ MM_WFD_SINK_COMMAND_PREPARE, /**< command for preparing wifi-display sink */
+ MM_WFD_SINK_COMMAND_CONNECT, /**< command for connecting wifi-display sink */
+ MM_WFD_SINK_COMMAND_START, /**< command for starting wifi-display sink */
+ MM_WFD_SINK_COMMAND_PAUSE, /**< command for pausing wifi-display sink */
+ MM_WFD_SINK_COMMAND_RESUME, /**< command for resuming wifi-display sink */
+ MM_WFD_SINK_COMMAND_DISCONNECT, /**< command for disconnecting wifi-display sink */
+ MM_WFD_SINK_COMMAND_UNPREPARE, /**< command for unpreparing wifi-display sink */
+ MM_WFD_SINK_COMMAND_DESTROY, /**< command for destroting wifi-display sink */
+ MM_WFD_SINK_COMMAND_NUM, /**< Number of wifi-display commands */
+} MMWFDSinkCommandType;
+
+/**
+ * * Enumerations of thread command.
+ * */
+typedef enum {
+ WFD_SINK_MANAGER_CMD_NONE = 0,
+ WFD_SINK_MANAGER_CMD_LINK_A_DECODEBIN,
+ WFD_SINK_MANAGER_CMD_LINK_V_DECODEBIN,
+ WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE,
+ WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE,
+ WFD_SINK_MANAGER_CMD_EXIT,
+} WFDSinkManagerCMDType;
+
+/**
+ * * Enumerations of resolution.
+ * */
+typedef enum {
+ MM_WFD_SINK_RESOLUTION_UNKNOWN = 0,
+ MM_WFD_SINK_RESOLUTION_1920x1080_P30 = (1 << 0), /**< W-1920, H-1080, 30 fps*/
+ MM_WFD_SINK_RESOLUTION_1280x720_P30 = (1 << 1), /**< W-1280, H-720, 30 fps*/
+ MM_WFD_SINK_RESOLUTION_960x540_P30 = (1 << 2), /**< W-960, H-540, 30 fps*/
+ MM_WFD_SINK_RESOLUTION_864x480_P30 = (1 << 3), /**< W-864, H-480, 30 fps*/
+ MM_WFD_SINK_RESOLUTION_720x480_P60 = (1 << 4), /**< W-720, H-480, 30 fps*/
+ MM_WFD_SINK_RESOLUTION_640x480_P60 = (1 << 5), /**< W-640, H-480, 60 fps*/
+ MM_WFD_SINK_RESOLUTION_640x360_P30 = (1 << 6), /**< W-640, H-360, 30 fps*/
+ MM_WFD_SINK_RESOLUTION_MAX = 128,
+} MMWFDSinkResolution;
+
+typedef struct {
+ gint codec;
+ gint width;
+ gint height;
+ gint frame_rate;
+} MMWFDSinkVideoStreamInfo;
+
+typedef struct {
+ gint codec;
+ gint channels;
+ gint sample_rate;
+ gint bitwidth;
+} MMWFDSinkAudioStreamInfo;
+
+typedef struct {
+ MMWFDSinkAudioStreamInfo audio_stream_info;
+ MMWFDSinkVideoStreamInfo video_stream_info;
+} MMWFDSinkStreamInfo;
+
+
+typedef struct {
+ gint id;
+ GstElement *gst;
+} MMWFDSinkGstElement;
+
+typedef struct {
+ MMWFDSinkGstElement *mainbin;
+ MMWFDSinkGstElement *a_decodebin;
+ MMWFDSinkGstElement *v_decodebin;
+ MMWFDSinkGstElement *a_sinkbin;
+ MMWFDSinkGstElement *v_sinkbin;
+} MMWFDSinkGstPipelineInfo;
+
+typedef struct {
+ MMWFDSinkStateType state; /* wfd current state */
+ MMWFDSinkStateType prev_state; /* wfd previous state */
+ MMWFDSinkStateType pending_state; /* wfd state which is going to now */
+} MMWFDSinkState;
+
+#define MMWFDSINK_GET_ATTRS(x_wfd) ((x_wfd)? ((mm_wfd_sink_t*)x_wfd)->attrs : (MMHandleType)NULL)
+
+typedef struct {
+ /* gstreamer pipeline */
+ MMWFDSinkGstPipelineInfo *pipeline;
+ gboolean audio_decodebin_is_linked;
+ gboolean video_decodebin_is_linked;
+
+ /* timestamp compensation */
+ gboolean need_to_reset_basetime;
+
+ GstClock *clock;
+ gint64 video_average_gap;
+ gint64 video_accumulated_gap;
+ gint64 video_buffer_count;
+ gint64 audio_average_gap;
+ gint64 audio_accumulated_gap;
+ gint64 audio_buffer_count;
+ GstClockTime last_buffer_timestamp;
+
+ /* attributes */
+ MMHandleType attrs;
+
+ /* state */
+ MMWFDSinkState state;
+
+ /* initialize values */
+ mm_wfd_sink_ini_t ini;
+
+ /* command */
+ MMWFDSinkCommandType cmd;
+ GMutex cmd_lock;
+ gboolean waiting_cmd;
+
+ /* stream information */
+ MMWFDSinkStreamInfo stream_info;
+
+ /* Message handling */
+ MMWFDMessageCallback msg_cb;
+ void *msg_user_data;
+
+ /* video resolution for negotiation */
+ MMWFDSinkResolution supportive_resolution;
+
+ GThread *manager_thread;
+ GMutex manager_thread_mutex;
+ GCond manager_thread_cond;
+ GList *manager_thread_cmd;
+ gboolean manager_thread_exit;
+} mm_wfd_sink_t;
+
+
+int _mm_wfd_sink_create(mm_wfd_sink_t **wfd_sink);
+int _mm_wfd_sink_destroy(mm_wfd_sink_t *wfd_sink);
+int _mm_wfd_sink_prepare(mm_wfd_sink_t *wfd_sink);
+int _mm_wfd_sink_unprepare(mm_wfd_sink_t *wfd_sink);
+int _mm_wfd_sink_connect(mm_wfd_sink_t *wfd_sink, const char *uri);
+int _mm_wfd_sink_disconnect(mm_wfd_sink_t *wfd_sink);
+int _mm_wfd_sink_start(mm_wfd_sink_t *wfd_sink);
+int _mm_wfd_sink_pause(mm_wfd_sink_t *wfd_sink);
+int _mm_wfd_sink_resume(mm_wfd_sink_t *wfd_sink);
+int _mm_wfd_set_message_callback(mm_wfd_sink_t *wfd_sink, MMWFDMessageCallback callback, void *user_data);
+int _mm_wfd_sink_get_resource(mm_wfd_sink_t *wfd_sink);
+int _mm_wfd_sink_set_resolution(mm_wfd_sink_t *wfd_sink, MMWFDSinkResolution resolution);
+
+int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink);
+int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink);
+int __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink);
+int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink);
+
+const gchar *_mm_wfds_sink_get_state_name(MMWFDSinkStateType state);
+
+#endif
+
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _MM_WFD_SINK_UTIL_H_
+#define _MM_WFD_SINK_UTIL_H_
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <mm_message.h>
+#include <mm_error.h>
+#include <mm_types.h>
+#include "mm_wfd_sink_dlog.h"
+
+#define MMWFDSINK_FREEIF(x) \
+ do {\
+ if ((x)) \
+ g_free((gpointer)(x)); \
+ (x) = NULL;\
+ } while (0);
+
+/* lock for commnad */
+#define MMWFDSINK_CMD_LOCK(x_wfd) \
+ if (x_wfd) \
+ g_mutex_lock(&(((mm_wfd_sink_t *)x_wfd)->cmd_lock));
+
+#define MMWFDSINK_CMD_UNLOCK(x_wfd) \
+ if (x_wfd) \
+ g_mutex_unlock(&(((mm_wfd_sink_t *)x_wfd)->cmd_lock));
+
+/* create element */
+#define MMWFDSINK_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket) \
+ do { \
+ if (x_name && (strlen(x_factory) > 1)) {\
+ x_bin[x_id].id = x_id;\
+ x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
+ if (! x_bin[x_id].gst) {\
+ wfd_sink_error("failed to create %s \n", x_factory);\
+ goto CREATE_ERROR;\
+ }\
+ wfd_sink_debug("%s is created \n", x_factory);\
+ if (x_add_bucket)\
+ element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
+ }\
+ } while (0);
+
+/* generating dot */
+#define MMWFDSINK_GENERATE_DOT_IF_ENABLED(x_wfd_sink, x_name) \
+ if (x_wfd_sink->ini.generate_dot) { \
+ wfd_sink_debug("create dot file : %s.dot", x_name);\
+ GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(x_wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst), \
+ GST_DEBUG_GRAPH_SHOW_ALL, x_name); \
+ }
+
+/* postint message */
+#define MMWFDSINK_POST_MESSAGE(x_wfd_sink, x_error_type, x_state_type) \
+ if (x_wfd_sink->msg_cb) { \
+ wfd_sink_debug("Message(error : %d, state : %d) will be posted using user callback\n", x_error_type, x_state_type); \
+ x_wfd_sink->msg_cb(x_error_type, x_state_type, x_wfd_sink->msg_user_data); \
+ }
+
+
+/* state */
+#define MMWFDSINK_CURRENT_STATE(x_wfd_sink) ((mm_wfd_sink_t *)x_wfd_sink)->state.state
+#define MMWFDSINK_PREVIOUS_STATE(x_wfd_sink) ((mm_wfd_sink_t *)x_wfd_sink)->state.prev_state
+#define MMWFDSINK_PENDING_STATE(x_wfd_sink) ((mm_wfd_sink_t *)x_wfd_sink)->state.pending_state
+#define MMWFDSINK_STATE_GET_NAME(x_state) _mm_wfds_sink_get_state_name(x_state)
+
+#define MMWFDSINK_PRINT_STATE(x_wfd_sink) \
+ wfd_sink_debug("--prev %s, current %s, pending %s--\n", \
+ MMWFDSINK_STATE_GET_NAME(MMWFDSINK_PREVIOUS_STATE(x_wfd_sink)), \
+ MMWFDSINK_STATE_GET_NAME(MMWFDSINK_CURRENT_STATE(x_wfd_sink)), \
+ MMWFDSINK_STATE_GET_NAME(MMWFDSINK_PENDING_STATE(x_wfd_sink)));
+
+#define MMWFDSINK_CHECK_STATE(x_wfd_sink, x_cmd) \
+ switch (__mm_wfd_sink_check_state((mm_wfd_sink_t *)x_wfd_sink, x_cmd)) \
+ { \
+ case MM_ERROR_NONE: \
+ break;\
+ case MM_ERROR_WFD_NO_OP: \
+ return MM_ERROR_NONE; \
+ break; \
+ default: \
+ return MM_ERROR_WFD_INVALID_STATE; \
+ break; \
+ }
+
+
+/* pad probe */
+void
+mm_wfd_sink_util_add_pad_probe(GstPad *pad, GstElement *element, const gchar *pad_name);
+void
+mm_wfd_sink_util_add_pad_probe_for_checking_first_buffer(GstPad *pad, GstElement *element, const gchar *pad_name);
+
+#define MMWFDSINK_PAD_PROBE(x_wfd_sink, x_pad, x_element, x_pad_name) \
+ if (x_wfd_sink) { \
+ if (x_wfd_sink->ini.enable_pad_probe) { \
+ mm_wfd_sink_util_add_pad_probe(x_pad, x_element, (const gchar*)x_pad_name); \
+ } else {\
+ mm_wfd_sink_util_add_pad_probe_for_checking_first_buffer (x_pad, x_element, (const gchar*)x_pad_name); \
+ }\
+ }
+
+void
+mm_wfd_sink_util_add_pad_probe_for_data_dump(GstElement *element, const gchar *pad_name);
+
+#define MMWFDSINK_TS_DATA_DUMP(x_wfd_sink, x_element, x_pad_name) \
+ if (x_wfd_sink && x_wfd_sink->ini.enable_ts_data_dump) { \
+ mm_wfd_sink_util_add_pad_probe_for_data_dump (x_element, (const gchar*)x_pad_name); \
+ }
+
+#endif
--- /dev/null
+/*
+* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+#ifndef __MM_WFD_SINK_WLCLIENT_H__
+#define __MM_WFD_SINK_WLCLIENT_H__
+#include <stdio.h>
+#include <tbm_bufmgr.h>
+#include <tizen-extension-client-protocol.h>
+#include <wayland-client.h>
+#include <mm_types.h>
+#include <mm_debug.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct
+{
+ struct wl_display *display;
+ struct wl_registry *registry;
+ struct tizen_surface *tz_surface;
+ struct tizen_resource *tz_resource;
+} wl_client;
+
+int mm_wfd_sink_wlclient_create (wl_client ** wlclient);
+int mm_wfd_sink_wlclient_get_wl_window_wl_surface_id (wl_client * wlclient, struct wl_surface *surface, struct wl_display *display);
+void mm_wfd_sink_wlclient_finalize (wl_client * wlclient);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_WFD_SINK_WLCLIENT_H__ */
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <gst/gst.h>
+
+#include "mm_wfd_sink_util.h"
+#include "mm_wfd_sink.h"
+#include "mm_wfd_sink_priv.h"
+#include "mm_wfd_sink_dlog.h"
+
+int mm_wfd_sink_create(MMHandleType *wfd_sink)
+{
+ mm_wfd_sink_t *new_wfd_sink = NULL;
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ result = _mm_wfd_sink_create(&new_wfd_sink);
+ if (result != MM_ERROR_NONE) {
+ wfd_sink_error("fail to create wi-fi display sink handle. ret[%d]", result);
+ *wfd_sink = (MMHandleType)NULL;
+ return result;
+ }
+
+ /* init wfd lock */
+ g_mutex_init(&new_wfd_sink->cmd_lock);
+
+ *wfd_sink = (MMHandleType)new_wfd_sink;
+
+ wfd_sink_debug_fleave();
+
+ return result;
+
+}
+
+int mm_wfd_sink_prepare(MMHandleType wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_prepare((mm_wfd_sink_t *)wfd_sink);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_connect(MMHandleType wfd_sink, const char *uri)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(uri, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_connect((mm_wfd_sink_t *)wfd_sink, uri);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_start(MMHandleType wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_start((mm_wfd_sink_t *)wfd_sink);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_pause(MMHandleType wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_pause((mm_wfd_sink_t *)wfd_sink);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_resume(MMHandleType wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_resume((mm_wfd_sink_t *)wfd_sink);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_disconnect(MMHandleType wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_disconnect((mm_wfd_sink_t *)wfd_sink);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_unprepare(MMHandleType wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_unprepare((mm_wfd_sink_t *)wfd_sink);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_destroy(MMHandleType wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+ mm_wfd_sink_t *sink_handle = NULL;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_destroy((mm_wfd_sink_t *)wfd_sink);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ g_mutex_clear(&(((mm_wfd_sink_t *)wfd_sink)->cmd_lock));
+
+ sink_handle = (mm_wfd_sink_t *)wfd_sink;
+ MMWFDSINK_FREEIF(sink_handle);
+
+ return result;
+}
+
+int mm_wfd_sink_set_message_callback(MMHandleType wfd_sink, MMWFDMessageCallback callback, void *user_data)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_set_message_callback((mm_wfd_sink_t *)wfd_sink, callback, user_data);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_set_attribute(MMHandleType wfd_sink, char **err_attr_name, const char *first_attribute_name, ...)
+{
+ int result = MM_ERROR_NONE;
+ va_list var_args;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(first_attribute_name, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ va_start(var_args, first_attribute_name);
+ result = _mmwfd_set_attribute(MMWFDSINK_GET_ATTRS(wfd_sink), err_attr_name, first_attribute_name, var_args);
+ va_end(var_args);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_get_video_resolution(MMHandleType wfd_sink, gint *width, gint *height)
+{
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(width, MM_ERROR_WFD_INVALID_ARGUMENT);
+ wfd_sink_return_val_if_fail(height, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ *width = wfd->stream_info.video_stream_info.width;
+ *height = wfd->stream_info.video_stream_info.height;
+
+ return MM_ERROR_NONE;
+}
+
+int mm_wfd_sink_get_video_framerate(MMHandleType wfd_sink, gint *frame_rate)
+{
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(frame_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ *frame_rate = wfd->stream_info.video_stream_info.frame_rate;
+
+ return MM_ERROR_NONE;
+}
+
+int mm_wfd_sink_set_resolution(MMHandleType wfd_sink, gint resolution)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+ MMWFDSINK_CMD_LOCK(wfd_sink);
+ result = _mm_wfd_sink_set_resolution((mm_wfd_sink_t *)wfd_sink, resolution);
+ MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+ return result;
+}
+
+int mm_wfd_sink_get_negotiated_video_codec(MMHandleType wfd_sink, gint *codec)
+{
+ int result = MM_ERROR_NONE;
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(codec, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd);
+
+ MMWFDSINK_PRINT_STATE(wfd);
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd);
+ if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+ cur_state != MM_WFD_SINK_STATE_PLAYING &&
+ cur_state != MM_WFD_SINK_STATE_PAUSED) {
+
+ wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
+ result = MM_ERROR_WFD_INVALID_STATE;
+ } else {
+ *codec = wfd->stream_info.video_stream_info.codec;
+ }
+
+ MMWFDSINK_CMD_UNLOCK(wfd);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int mm_wfd_sink_get_negotiated_video_resolution(MMHandleType wfd_sink, gint *width, gint *height)
+{
+ int result = MM_ERROR_NONE;
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(width, MM_ERROR_WFD_INVALID_ARGUMENT);
+ wfd_sink_return_val_if_fail(height, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd);
+
+ MMWFDSINK_PRINT_STATE(wfd);
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd);
+ if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+ cur_state != MM_WFD_SINK_STATE_PLAYING &&
+ cur_state != MM_WFD_SINK_STATE_PAUSED) {
+
+ wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
+ result = MM_ERROR_WFD_INVALID_STATE;
+ } else {
+ *width = wfd->stream_info.video_stream_info.width;
+ *height = wfd->stream_info.video_stream_info.height;
+ }
+
+ MMWFDSINK_CMD_UNLOCK(wfd);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int mm_wfd_sink_get_negotiated_video_frame_rate(MMHandleType wfd_sink, gint *frame_rate)
+{
+ int result = MM_ERROR_NONE;
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(frame_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd);
+
+ MMWFDSINK_PRINT_STATE(wfd);
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd);
+ if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+ cur_state != MM_WFD_SINK_STATE_PLAYING &&
+ cur_state != MM_WFD_SINK_STATE_PAUSED) {
+
+ wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
+ result = MM_ERROR_WFD_INVALID_STATE;
+ } else {
+ *frame_rate = wfd->stream_info.video_stream_info.frame_rate;
+ }
+
+ MMWFDSINK_CMD_UNLOCK(wfd);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int mm_wfd_sink_get_negotiated_audio_codec(MMHandleType wfd_sink, gint *codec)
+{
+ int result = MM_ERROR_NONE;
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(codec, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd);
+
+ MMWFDSINK_PRINT_STATE(wfd);
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd);
+ if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+ cur_state != MM_WFD_SINK_STATE_PLAYING &&
+ cur_state != MM_WFD_SINK_STATE_PAUSED) {
+
+ wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
+ result = MM_ERROR_WFD_INVALID_STATE;
+ } else {
+ *codec = wfd->stream_info.audio_stream_info.codec;
+ }
+
+ MMWFDSINK_CMD_UNLOCK(wfd);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int mm_wfd_sink_get_negotiated_audio_channel(MMHandleType wfd_sink, gint *channel)
+{
+ int result = MM_ERROR_NONE;
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(channel, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd);
+
+ MMWFDSINK_PRINT_STATE(wfd);
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd);
+ if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+ cur_state != MM_WFD_SINK_STATE_PLAYING &&
+ cur_state != MM_WFD_SINK_STATE_PAUSED) {
+
+ wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
+ result = MM_ERROR_WFD_INVALID_STATE;
+ } else {
+ *channel = wfd->stream_info.audio_stream_info.channels;
+ }
+
+ MMWFDSINK_CMD_UNLOCK(wfd);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int mm_wfd_sink_get_negotiated_audio_sample_rate(MMHandleType wfd_sink, gint *sample_rate)
+{
+ int result = MM_ERROR_NONE;
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(sample_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd);
+
+ MMWFDSINK_PRINT_STATE(wfd);
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd);
+ if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+ cur_state != MM_WFD_SINK_STATE_PLAYING &&
+ cur_state != MM_WFD_SINK_STATE_PAUSED) {
+
+ wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
+ result = MM_ERROR_WFD_INVALID_STATE;
+ } else {
+ *sample_rate = wfd->stream_info.audio_stream_info.sample_rate;
+ }
+
+ MMWFDSINK_CMD_UNLOCK(wfd);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int mm_wfd_sink_get_negotiated_audio_bitwidth(MMHandleType wfd_sink, gint *bitwidth)
+{
+ int result = MM_ERROR_NONE;
+ mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(bitwidth, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ MMWFDSINK_CMD_LOCK(wfd);
+
+ MMWFDSINK_PRINT_STATE(wfd);
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd);
+ if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+ cur_state != MM_WFD_SINK_STATE_PLAYING &&
+ cur_state != MM_WFD_SINK_STATE_PAUSED) {
+
+ wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
+ result = MM_ERROR_WFD_INVALID_STATE;
+ } else {
+ *bitwidth = wfd->stream_info.audio_stream_info.bitwidth;
+ }
+
+ MMWFDSINK_CMD_UNLOCK(wfd);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "mm_wfd_sink_attrs.h"
+
+typedef struct {
+ char *name;
+ int value_type;
+ int flags; /* r, w */
+ void *default_value;
+ int valid_type;
+ int value_min;
+ int value_max;
+} MMWfdAttrsSpec;
+
+/*static gboolean __mmwfd_apply_attribute(MMHandleType handle, const char *attribute_name); */
+
+MMHandleType
+_mmwfd_construct_attribute(MMHandleType handle)
+{
+ int idx = 0;
+ MMHandleType attrs = 0;
+ int num_of_attrs = 0;
+ mmf_attrs_construct_info_t *base = NULL;
+
+ debug_fenter();
+
+ return_val_if_fail(handle, (MMHandleType) NULL);
+
+ MMWfdAttrsSpec wfd_attrs[] = {
+ {
+ (char *)"server_ip",
+ MM_ATTRS_TYPE_STRING,
+ MM_ATTRS_FLAG_RW,
+ (void *)"127.0.0.1",
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0
+ },
+
+ {
+ (char *)"server_port",
+ MM_ATTRS_TYPE_STRING,
+ MM_ATTRS_FLAG_RW,
+ (void *)"8554",
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0
+ },
+
+ {
+ (char *)"max_client_count",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *)1,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 10
+ },
+ /* Initialized with invalid native type, if a valid value is set then only this atribute will be considered */
+ {
+ (char *)"native_resolution",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 3
+ },
+ /* Initialized with invalid resolution, if a valid value is set then only this atribute will be considered */
+ {
+ (char *)"prefered_resolutions",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *)2147483647,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 2147483647
+ },
+ /* Initialized with invalid uibc option, if a valid value is set then only this atribute will be considered */
+ {
+ (char *)"set_hdcp",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *)2,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 2
+ },
+ {
+ (char *)"display_rotate",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 3
+ },
+ {
+ (char *)"display_src_crop_x",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_src_crop_y",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_src_crop_width",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_src_crop_height",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_roi_x",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_roi_y",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_roi_width",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 480,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_roi_height",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 800,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_roi_mode",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) MM_DISPLAY_METHOD_CUSTOM_ROI_FULL_SCREEN,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_DISPLAY_METHOD_CUSTOM_ROI_FULL_SCREEN,
+ MM_DISPLAY_METHOD_CUSTOM_ROI_LETER_BOX
+ },
+ {
+ (char *)"display_rotation",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) MM_DISPLAY_ROTATION_NONE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_DISPLAY_ROTATION_NONE,
+ MM_DISPLAY_ROTATION_270
+ },
+ {
+ (char *)"display_visible",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) TRUE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1
+ },
+ {
+ (char *)"display_method",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) MM_DISPLAY_METHOD_LETTER_BOX,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_DISPLAY_METHOD_LETTER_BOX,
+ MM_DISPLAY_METHOD_CUSTOM_ROI
+ },
+ {
+ (char *)"display_overlay",
+ MM_ATTRS_TYPE_DATA,
+ MM_ATTRS_FLAG_RW,
+ (void *) NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0
+ },
+ {
+ (char *)"display_overlay_user_data",
+ MM_ATTRS_TYPE_DATA,
+ MM_ATTRS_FLAG_RW,
+ (void *) NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0
+ },
+ {
+ (char *)"display_zoom",
+ MM_ATTRS_TYPE_DOUBLE,
+ MM_ATTRS_FLAG_RW,
+ (void *) 1,
+ MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
+ 1.0,
+ 9.0
+ },
+ {
+ (char *)"display_surface_type",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) MM_DISPLAY_SURFACE_OVERLAY,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_DISPLAY_SURFACE_OVERLAY,
+ MM_DISPLAY_SURFACE_REMOTE
+ },
+ {
+ (char *)"display_width", /* dest width of fimcconvert ouput */
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_height", /* dest height of fimcconvert ouput */
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_evas_do_scaling",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) TRUE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ FALSE,
+ TRUE
+ },
+ {
+ (char *)"display_x",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"display_y",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 4096
+ },
+ {
+ (char *)"hdcp_version",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 2
+ },
+ {
+ (char *)"hdcp_port",
+ MM_ATTRS_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void *) 0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 2147483647
+ },
+ };
+
+ num_of_attrs = ARRAY_SIZE(wfd_attrs);
+
+ base = (mmf_attrs_construct_info_t *)malloc(num_of_attrs * sizeof(mmf_attrs_construct_info_t));
+
+ if (!base) {
+ debug_error("Cannot create mmwfd attribute\n");
+ goto ERROR;
+ }
+
+ /* initialize values of attributes */
+ for (idx = 0; idx < num_of_attrs; idx++) {
+ base[idx].name = wfd_attrs[idx].name;
+ base[idx].value_type = wfd_attrs[idx].value_type;
+ base[idx].flags = wfd_attrs[idx].flags;
+ base[idx].default_value = wfd_attrs[idx].default_value;
+ }
+
+ attrs = mmf_attrs_new_from_data(
+ "mmwfd_attrs",
+ base,
+ num_of_attrs,
+ NULL,
+ NULL);
+
+ if (base) {
+ g_free(base);
+ base = NULL;
+ }
+
+ if (!attrs) {
+ debug_error("Cannot create mmwfd attribute\n");
+ goto ERROR;
+ }
+
+ /* set validity type and range */
+ for (idx = 0; idx < num_of_attrs; idx++) {
+ switch (wfd_attrs[idx].valid_type) {
+ case MM_ATTRS_VALID_TYPE_INT_RANGE: {
+ mmf_attrs_set_valid_type(attrs, idx, MM_ATTRS_VALID_TYPE_INT_RANGE);
+ mmf_attrs_set_valid_range(attrs, idx,
+ wfd_attrs[idx].value_min,
+ wfd_attrs[idx].value_max,
+ (int)wfd_attrs[idx].default_value);
+ }
+ break;
+
+ case MM_ATTRS_VALID_TYPE_INT_ARRAY:
+ case MM_ATTRS_VALID_TYPE_DOUBLE_ARRAY:
+ case MM_ATTRS_VALID_TYPE_DOUBLE_RANGE:
+ default:
+ break;
+ }
+ }
+
+ debug_fleave();
+
+ return attrs;
+
+ERROR:
+ _mmwfd_deconstruct_attribute(attrs);
+
+ return (MMHandleType)NULL;
+}
+
+void
+_mmwfd_deconstruct_attribute(MMHandleType handle)
+{
+ debug_fenter();
+
+ return_if_fail(handle);
+
+ if (handle)
+ mmf_attrs_free(handle);
+
+ debug_fleave();
+}
+
+int
+_mmwfd_get_attribute(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list args_list)
+{
+ int result = MM_ERROR_NONE;
+ MMHandleType attrs = 0;
+
+ debug_fenter();
+
+ /* NOTE : Don't need to check err_attr_name because it can be set NULL */
+ /* if it's not want to know it. */
+ return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
+ return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ attrs = handle;
+
+ return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ result = mm_attrs_get_valist(attrs, err_attr_name, attribute_name, args_list);
+
+ if (result != MM_ERROR_NONE)
+ debug_error("failed to get %s attribute\n", attribute_name);
+
+ debug_fleave();
+
+ return result;
+}
+
+int
+_mmwfd_set_attribute(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list args_list)
+{
+ int result = MM_ERROR_NONE;
+ MMHandleType attrs = 0;
+
+ debug_fenter();
+
+ /* NOTE : Don't need to check err_attr_name because it can be set NULL */
+ /* if it's not want to know it. */
+ return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
+ return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ attrs = handle;
+
+ return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ /* set attributes and commit them */
+ result = mm_attrs_set_valist(attrs, err_attr_name, attribute_name, args_list);
+
+ if (result != MM_ERROR_NONE) {
+ debug_error("failed to set %s attribute\n", attribute_name);
+ return result;
+ }
+
+ /*__mmwfd_apply_attribute(handle, attribute_name); */
+
+ debug_fleave();
+
+ return result;
+}
+
+/* Currently not used. */
+/*static gboolean
+__mmwfd_apply_attribute(MMHandleType handle, const char *attribute_name)
+{
+ MMHandleType attrs = 0;
+ mm_wfd_t* wfd = 0;
+
+ debug_fenter();
+
+ return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
+ return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ attrs = handle;
+
+ return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ wfd = (mm_wfd_t*)handle;
+
+ // TODO: This function is not useful at this moment
+
+ debug_fleave();
+
+ return TRUE;
+}*/
+
+int
+_mmwfd_get_attributes_info(MMHandleType handle, const char *attribute_name, MMWfdAttrsInfo *dst_info)
+{
+ int result = MM_ERROR_NONE;
+ MMHandleType attrs = 0;
+ MMAttrsInfo src_info = {0, };
+
+ debug_fenter();
+
+ return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
+ return_val_if_fail(dst_info, MM_ERROR_COMMON_INVALID_ARGUMENT);
+ return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ attrs = handle;
+
+ return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ result = mm_attrs_get_info_by_name(attrs, attribute_name, &src_info);
+
+ if (result != MM_ERROR_NONE) {
+ debug_error("failed to get attribute info\n");
+ return result;
+ }
+
+ memset(dst_info, 0x00, sizeof(MMWfdAttrsInfo));
+
+ dst_info->type = src_info.type;
+ dst_info->flag = src_info.flag;
+ dst_info->validity_type = src_info.validity_type;
+
+ switch (src_info.validity_type) {
+ case MM_ATTRS_VALID_TYPE_INT_ARRAY:
+ dst_info->int_array.array = src_info.int_array.array;
+ dst_info->int_array.count = src_info.int_array.count;
+ dst_info->int_array.d_val = src_info.int_array.dval;
+ break;
+
+ case MM_ATTRS_VALID_TYPE_INT_RANGE:
+ dst_info->int_range.min = src_info.int_range.min;
+ dst_info->int_range.max = src_info.int_range.max;
+ dst_info->int_range.d_val = src_info.int_range.dval;
+ break;
+
+ case MM_ATTRS_VALID_TYPE_DOUBLE_ARRAY:
+ dst_info->double_array.array = src_info.double_array.array;
+ dst_info->double_array.count = src_info.double_array.count;
+ dst_info->double_array.d_val = src_info.double_array.dval;
+ break;
+
+ case MM_ATTRS_VALID_TYPE_DOUBLE_RANGE:
+ dst_info->double_range.min = src_info.double_range.min;
+ dst_info->double_range.max = src_info.double_range.max;
+ dst_info->double_range.d_val = src_info.double_range.dval;
+ break;
+
+ default:
+ break;
+ }
+
+ debug_fleave();
+
+ return result;
+}
+
+
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <stdlib.h>
+#include <iniparser.h>
+#include <mm_error.h>
+#include "mm_wfd_sink_ini.h"
+#include "mm_wfd_sink_dlog.h"
+
+static gboolean loaded = FALSE;
+
+/* global variables here */
+#ifdef MM_WFD_SINK_DEFAULT_INI
+static gboolean __generate_sink_default_ini(void);
+#endif
+
+static void __mm_wfd_sink_ini_check_status(void);
+
+/* macro */
+#define MM_WFD_SINK_INI_GET_STRING(x_dict, x_item, x_ini, x_default) \
+ do { \
+ gchar *str = NULL; \
+ gint length = 0; \
+ \
+ str = iniparser_getstring(x_dict, x_ini, (char *)x_default); \
+ if (str) { \
+ length = strlen(str); \
+ if ((length > 1) && (length < WFD_SINK_INI_MAX_STRLEN)) \
+ strncpy(x_item, str, WFD_SINK_INI_MAX_STRLEN-1); \
+ else \
+ strncpy(x_item, x_default, WFD_SINK_INI_MAX_STRLEN-1); \
+ } else { \
+ strncpy(x_item, x_default, WFD_SINK_INI_MAX_STRLEN-1); \
+ } \
+ } while (0);
+
+#ifdef MM_WFD_SINK_DEFAULT_INI
+static
+gboolean __generate_sink_default_ini(void)
+{
+ FILE *fp = NULL;
+ const gchar *default_ini = MM_WFD_SINK_DEFAULT_INI;
+
+
+ /* create new file */
+ fp = fopen(MM_WFD_SINK_INI_DEFAULT_PATH, "wt");
+
+ if (!fp) {
+ return FALSE;
+ }
+
+ /* writing default ini file */
+ if (strlen(default_ini) != fwrite(default_ini, 1, strlen(default_ini), fp)) {
+ fclose(fp);
+ return FALSE;
+ }
+
+ fclose(fp);
+ return TRUE;
+}
+#endif
+
+int
+mm_wfd_sink_ini_load(mm_wfd_sink_ini_t *ini)
+{
+ dictionary *dict = NULL;
+
+ wfd_sink_debug_fenter();
+
+
+ __mm_wfd_sink_ini_check_status();
+
+ /* first, try to load existing ini file */
+ dict = iniparser_load(MM_WFD_SINK_INI_DEFAULT_PATH);
+
+ /* if no file exists. create one with set of default values */
+ if (!dict) {
+#ifdef MM_WFD_SINK_DEFAULT_INI
+ wfd_sink_debug("No inifile found. create default ini file.\n");
+ if (FALSE == __generate_sink_default_ini()) {
+ wfd_sink_error("Creating default ini file failed. Use default values.\n");
+ } else {
+ /* load default ini */
+ dict = iniparser_load(MM_WFD_SINK_INI_DEFAULT_PATH);
+ }
+#else
+ wfd_sink_error("No ini file found. \n");
+
+ return MM_ERROR_FILE_NOT_FOUND;
+#endif
+ }
+
+ /* get ini values */
+ memset(ini, 0, sizeof(mm_wfd_sink_ini_t));
+
+ if (dict) { /* if dict is available */
+ /* general */
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[0], "general:gstparam1", DEFAULT_GST_PARAM);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[1], "general:gstparam2", DEFAULT_GST_PARAM);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[2], "general:gstparam3", DEFAULT_GST_PARAM);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[3], "general:gstparam4", DEFAULT_GST_PARAM);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->gst_param[4], "general:gstparam5", DEFAULT_GST_PARAM);
+ ini->generate_dot = iniparser_getboolean(dict, "general:generate dot", DEFAULT_GENERATE_DOT);
+ ini->enable_pad_probe = iniparser_getboolean(dict, "general:enable pad probe", DEFAULT_ENABLE_PAD_PROBE);
+ ini->state_change_timeout = iniparser_getint(dict, "general:state change timeout", DEFAULT_STATE_CHANGE_TIMEOUT);
+ ini->set_debug_property = iniparser_getboolean(dict, "general:set debug property", DEFAULT_SET_DEBUG_PROPERTY);
+ ini->enable_asm = iniparser_getboolean(dict, "general:enable asm", DEFAULT_ENABLE_ASM);
+ ini->jitter_buffer_latency = iniparser_getint(dict, "general:jitter buffer latency", DEFAULT_JITTER_BUFFER_LATENCY);
+ ini->enable_retransmission = iniparser_getboolean(dict, "general:enable retransmission", DEFAULT_ENABLE_RETRANSMISSION);
+ ini->enable_reset_basetime = iniparser_getboolean(dict, "general:enable reset basetime", DEFAULT_ENABLE_RESET_BASETIME);
+ ini->video_sink_max_lateness = iniparser_getint(dict, "general:video sink max lateness", DEFAULT_VIDEO_SINK_MAX_LATENESS);
+ ini->sink_ts_offset = iniparser_getint(dict, "general:sink ts offset", DEFAULT_SINK_TS_OFFSET);
+ ini->audio_sink_async = iniparser_getboolean(dict, "general:audio sink async", DEFAULT_AUDIO_SINK_ASYNC);
+ ini->video_sink_async = iniparser_getboolean(dict, "general:video sink async", DEFAULT_VIDEO_SINK_ASYNC);
+ ini->enable_ts_data_dump = iniparser_getboolean(dict, "general:enable ts data dump", DEFAULT_ENABLE_TS_DATA_DUMP);
+ ini->enable_wfdsrc_pad_probe = iniparser_getboolean(dict, "general:enable wfdsrc pad probe", DEFAULT_ENABLE_WFDRTSPSRC_PAD_PROBE);
+
+
+ /* pipeline */
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_source, "pipeline:wfdsrc element", DEFAULT_NAME_OF_SOURCE);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_tsdemux, "pipeline:tsdemux element", DEFAULT_NAME_OF_TSDEMUX);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_audio_hdcp, "pipeline:audio hdcp element", DEFAULT_NAME_OF_AUDIO_HDCP);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_aac_parser, "pipeline:aac parser element", DEFAULT_NAME_OF_AAC_PARSER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_aac_decoder, "pipeline:aac decoder element", DEFAULT_NAME_OF_AAC_DECODER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_ac3_parser, "pipeline:ac3 parser element", DEFAULT_NAME_OF_AC3_PARSER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_ac3_decoder, "pipeline:ac3 decoder element", DEFAULT_NAME_OF_AC3_DECODER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_lpcm_converter, "pipeline:lpcm converter element", DEFAULT_NAME_OF_LPCM_CONVERTER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_lpcm_filter, "pipeline:lpcm filter element", DEFAULT_NAME_OF_LPCM_FILTER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_audio_resampler, "pipeline:audio resampler element", DEFAULT_NAME_OF_AUDIO_RESAMPLER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_audio_volume, "pipeline:audio volume element", DEFAULT_NAME_OF_AUDIO_VOLUME);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_audio_sink, "pipeline:audio sink element", DEFAULT_NAME_OF_AUDIO_SINK);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_hdcp, "pipeline:video hdcp element", DEFAULT_NAME_OF_VIDEO_HDCP);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_parser, "pipeline:video parser element", DEFAULT_NAME_OF_VIDEO_PARSER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_capssetter, "pipeline:video capssetter element", DEFAULT_NAME_OF_VIDEO_CAPSSETTER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_decoder, "pipeline:video decoder element", DEFAULT_NAME_OF_VIDEO_DECODER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_converter, "pipeline:video converter element", DEFAULT_NAME_OF_VIDEO_CONVERTER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_filter, "pipeline:video filter element", DEFAULT_NAME_OF_VIDEO_FILTER);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_sink, "pipeline:video sink element", DEFAULT_NAME_OF_VIDEO_SINK);
+ MM_WFD_SINK_INI_GET_STRING(dict, ini->name_of_video_evas_sink, "pipeline:video evas sink element", DEFAULT_NAME_OF_EVAS_VIDEO_SINK);
+
+ /* audio parameter*/
+ ini->audio_codec = iniparser_getint(dict, "audio param:audio codec", DEFAULT_AUDIO_CODEC);
+ ini->audio_latency = iniparser_getint(dict, "audio param:audio latency", DEFAULT_AUDIO_LATENCY);
+ ini->audio_channel = iniparser_getint(dict, "audio param:audio channels", DEFAULT_AUDIO_CHANNELS);
+ ini->audio_sampling_frequency = iniparser_getint(dict, "audio param:audio sampling frequency", DEFAULT_AUDIO_SAMP_FREQUENCY);
+
+ /* video parameter*/
+ ini->video_codec = iniparser_getint(dict, "video param:video codec", DEFAULT_VIDEO_CODEC);
+ ini->video_native_resolution = iniparser_getint(dict, "video param:video native resolution", DEFAULT_VIDEO_NATIVE_RESOLUTION);
+ ini->video_cea_support = iniparser_getint(dict, "video param:video cea support", DEFAULT_VIDEO_CEA_SUPPORT);
+ ini->video_vesa_support = iniparser_getint(dict, "video param:video vesa support", DEFAULT_VIDEO_VESA_SUPPORT);
+ ini->video_hh_support = iniparser_getint(dict, "video param:video hh support", DEFAULT_VIDEO_HH_SUPPORT);
+ ini->video_profile = iniparser_getint(dict, "video param:video profile", DEFAULT_VIDEO_PROFILE);
+ ini->video_level = iniparser_getint(dict, "video param:video level", DEFAULT_VIDEO_LEVEL);
+ ini->video_latency = iniparser_getint(dict, "video param:video latency", DEFAULT_VIDEO_LATENCY);
+ ini->video_vertical_resolution = iniparser_getint(dict, "video param:video vertical resolution", DEFAULT_VIDEO_VERTICAL_RESOLUTION);
+ ini->video_horizontal_resolution = iniparser_getint(dict, "video param:video horizontal resolution", DEFAULT_VIDEO_HORIZONTAL_RESOLUTION);
+ ini->video_minimum_slicing = iniparser_getint(dict, "video param:video minimum slicesize", DEFAULT_VIDEO_MIN_SLICESIZE);
+ ini->video_slice_enc_param = iniparser_getint(dict, "video param:video slice encoding params", DEFAULT_VIDEO_SLICE_ENC_PARAM);
+ ini->video_framerate_control_support = iniparser_getint(dict, "video param:video framerate control support", DEFAULT_VIDEO_FRAMERATE_CONTROL);
+
+ /* hdcp parameter*/
+ ini->hdcp_content_protection = iniparser_getint(dict, "hdcp param:hdcp content protection", DEFAULT_HDCP_CONTENT_PROTECTION);
+ ini->hdcp_port_no = iniparser_getint(dict, "hdcp param:hdcp port no", DEFAULT_HDCP_PORT_NO);
+ } else { /* if dict is not available just fill the structure with default value */
+ wfd_sink_error("failed to load ini. using hardcoded default\n");
+
+ /* general */
+ strncpy(ini->gst_param[0], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->gst_param[1], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->gst_param[2], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->gst_param[3], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->gst_param[4], DEFAULT_GST_PARAM, WFD_SINK_INI_MAX_STRLEN - 1);
+ ini->generate_dot = DEFAULT_GENERATE_DOT;
+ ini->enable_pad_probe = DEFAULT_ENABLE_PAD_PROBE;
+ ini->state_change_timeout = DEFAULT_STATE_CHANGE_TIMEOUT;
+ ini->set_debug_property = DEFAULT_SET_DEBUG_PROPERTY;
+ ini->enable_asm = DEFAULT_ENABLE_ASM;
+ ini->jitter_buffer_latency = DEFAULT_JITTER_BUFFER_LATENCY;
+ ini->enable_retransmission = DEFAULT_ENABLE_RETRANSMISSION;
+ ini->enable_reset_basetime = DEFAULT_ENABLE_RESET_BASETIME;
+ ini->video_sink_max_lateness = DEFAULT_VIDEO_SINK_MAX_LATENESS;
+ ini->sink_ts_offset = DEFAULT_SINK_TS_OFFSET;
+ ini->enable_ts_data_dump = DEFAULT_ENABLE_TS_DATA_DUMP;
+ ini->enable_wfdsrc_pad_probe = DEFAULT_ENABLE_WFDRTSPSRC_PAD_PROBE;
+
+ /* pipeline */
+ strncpy(ini->name_of_source, DEFAULT_NAME_OF_TSDEMUX, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_tsdemux, DEFAULT_NAME_OF_TSDEMUX, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_audio_hdcp, DEFAULT_NAME_OF_AUDIO_HDCP, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_aac_parser, DEFAULT_NAME_OF_AAC_PARSER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_aac_decoder, DEFAULT_NAME_OF_AAC_DECODER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_ac3_parser, DEFAULT_NAME_OF_AC3_PARSER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_ac3_decoder, DEFAULT_NAME_OF_AC3_DECODER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_lpcm_converter, DEFAULT_NAME_OF_LPCM_CONVERTER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_lpcm_filter, DEFAULT_NAME_OF_LPCM_FILTER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_audio_resampler, DEFAULT_NAME_OF_AUDIO_RESAMPLER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_audio_volume, DEFAULT_NAME_OF_AUDIO_VOLUME, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_audio_sink, DEFAULT_NAME_OF_AUDIO_SINK, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_video_hdcp, DEFAULT_NAME_OF_VIDEO_HDCP, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_video_parser, DEFAULT_NAME_OF_VIDEO_PARSER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_video_capssetter, DEFAULT_NAME_OF_VIDEO_CAPSSETTER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_video_decoder, DEFAULT_NAME_OF_VIDEO_DECODER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_video_converter, DEFAULT_NAME_OF_VIDEO_CONVERTER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_video_filter, DEFAULT_NAME_OF_VIDEO_FILTER, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_video_sink, DEFAULT_NAME_OF_VIDEO_SINK, WFD_SINK_INI_MAX_STRLEN - 1);
+ strncpy(ini->name_of_video_evas_sink, DEFAULT_NAME_OF_EVAS_VIDEO_SINK, WFD_SINK_INI_MAX_STRLEN - 1);
+
+ /* audio parameter*/
+ ini->audio_codec = DEFAULT_AUDIO_CODEC;
+ ini->audio_latency = DEFAULT_AUDIO_LATENCY;
+ ini->audio_channel = DEFAULT_AUDIO_CHANNELS;
+ ini->audio_sampling_frequency = DEFAULT_AUDIO_SAMP_FREQUENCY;
+
+ /* video parameter*/
+ ini->video_codec = DEFAULT_VIDEO_CODEC;
+ ini->video_native_resolution = DEFAULT_VIDEO_NATIVE_RESOLUTION;
+ ini->video_cea_support = DEFAULT_VIDEO_CEA_SUPPORT;
+ ini->video_vesa_support = DEFAULT_VIDEO_VESA_SUPPORT;
+ ini->video_hh_support = DEFAULT_VIDEO_HH_SUPPORT;
+ ini->video_profile = DEFAULT_VIDEO_PROFILE;
+ ini->video_level = DEFAULT_VIDEO_LEVEL;
+ ini->video_latency = DEFAULT_VIDEO_LATENCY;
+ ini->video_vertical_resolution = DEFAULT_VIDEO_VERTICAL_RESOLUTION;
+ ini->video_horizontal_resolution = DEFAULT_VIDEO_HORIZONTAL_RESOLUTION;
+ ini->video_minimum_slicing = DEFAULT_VIDEO_MIN_SLICESIZE;
+ ini->video_slice_enc_param = DEFAULT_VIDEO_SLICE_ENC_PARAM;
+ ini->video_framerate_control_support = DEFAULT_VIDEO_FRAMERATE_CONTROL;
+
+ /* hdcp parameter*/
+ ini->hdcp_content_protection = DEFAULT_HDCP_CONTENT_PROTECTION;
+ ini->hdcp_port_no = DEFAULT_HDCP_PORT_NO;
+ }
+
+ /* free dict as we got our own structure */
+ iniparser_freedict(dict);
+
+
+ /* dump structure */
+ wfd_sink_debug("W-Fi Display Sink Initial Settings-----------------------------------\n");
+
+ /* general */
+ wfd_sink_debug("gst_param1 : %s\n", ini->gst_param[0]);
+ wfd_sink_debug("gst_param2 : %s\n", ini->gst_param[1]);
+ wfd_sink_debug("gst_param3 : %s\n", ini->gst_param[2]);
+ wfd_sink_debug("gst_param4 : %s\n", ini->gst_param[3]);
+ wfd_sink_debug("gst_param5 : %s\n", ini->gst_param[4]);
+ wfd_sink_debug("generate_dot : %d\n", ini->generate_dot);
+ if (ini->generate_dot == TRUE) {
+ wfd_sink_debug("generate_dot is TRUE, dot file will be stored into /tmp/\n");
+ g_setenv("GST_DEBUG_DUMP_DOT_DIR", "/tmp/", FALSE);
+ }
+ wfd_sink_debug("enable_pad_probe : %d\n", ini->enable_pad_probe);
+ wfd_sink_debug("state_change_timeout(sec) : %d\n", ini->state_change_timeout);
+ wfd_sink_debug("set_debug_property : %d\n", ini->set_debug_property);
+ wfd_sink_debug("enable_asm : %d\n", ini->enable_asm);
+ wfd_sink_debug("jitter_buffer_latency(msec) : %d\n", ini->jitter_buffer_latency);
+ wfd_sink_debug("enable_retransmission : %d\n", ini->enable_retransmission);
+ wfd_sink_debug("enable_reset_basetime : %d\n", ini->enable_reset_basetime);
+ wfd_sink_debug("video_sink_max_lateness(nsec) : %d\n", ini->video_sink_max_lateness);
+ wfd_sink_debug("sink_ts_offset(nsec) : %d\n", ini->sink_ts_offset);
+ wfd_sink_debug("audio_sink_async : %d\n", ini->audio_sink_async);
+ wfd_sink_debug("video_sink_async : %d\n", ini->video_sink_async);
+ wfd_sink_debug("enable_ts_data_dump : %d\n", ini->enable_ts_data_dump);
+ wfd_sink_debug("enable_wfdsrc_pad_probe : %d\n", ini->enable_wfdsrc_pad_probe);
+
+ /* pipeline */
+ wfd_sink_debug("name_of_source : %s\n", ini->name_of_source);
+ wfd_sink_debug("name_of_tsdemux : %s\n", ini->name_of_tsdemux);
+ wfd_sink_debug("name_of_audio_hdcp : %s\n", ini->name_of_audio_hdcp);
+ wfd_sink_debug("name_of_aac_parser : %s\n", ini->name_of_aac_parser);
+ wfd_sink_debug("name_of_aac_decoder : %s\n", ini->name_of_aac_decoder);
+ wfd_sink_debug("name_of_ac3_parser : %s\n", ini->name_of_ac3_parser);
+ wfd_sink_debug("name_of_ac3_decoder : %s\n", ini->name_of_ac3_decoder);
+ wfd_sink_debug("name_of_lpcm_converter : %s\n", ini->name_of_lpcm_converter);
+ wfd_sink_debug("name_of_lpcm_filter : %s\n", ini->name_of_lpcm_filter);
+ wfd_sink_debug("name_of_audio_resampler : %s\n", ini->name_of_audio_resampler);
+ wfd_sink_debug("name_of_audio_volume : %s\n", ini->name_of_audio_volume);
+ wfd_sink_debug("name_of_audio_sink : %s\n", ini->name_of_audio_sink);
+ wfd_sink_debug("name_of_video_hdcp : %s\n", ini->name_of_video_hdcp);
+ wfd_sink_debug("name_of_video_parser : %s\n", ini->name_of_video_parser);
+ wfd_sink_debug("name_of_video_capssetter : %s\n", ini->name_of_video_capssetter);
+ wfd_sink_debug("name_of_video_decoder : %s\n", ini->name_of_video_decoder);
+ wfd_sink_debug("name_of_video_converter : %s\n", ini->name_of_video_converter);
+ wfd_sink_debug("name_of_video_filter : %s\n", ini->name_of_video_filter);
+ wfd_sink_debug("name_of_video_sink : %s\n", ini->name_of_video_sink);
+ wfd_sink_debug("name_of_video_evas_sink : %s\n", ini->name_of_video_evas_sink);
+
+ /* audio parameter*/
+ wfd_sink_debug("audio_codec : %x\n", ini->audio_codec);
+ wfd_sink_debug("audio_latency : %d\n", ini->audio_latency);
+ wfd_sink_debug("audio_channel : %x\n", ini->audio_channel);
+ wfd_sink_debug("audio_sampling_frequency : %x\n", ini->audio_sampling_frequency);
+
+ /* video parameter*/
+ wfd_sink_debug("video_codec : %x\n", ini->video_codec);
+ wfd_sink_debug("video_native_resolution : %x\n", ini->video_native_resolution);
+ wfd_sink_debug("video_cea_support : %x\n", ini->video_cea_support);
+ wfd_sink_debug("video_vesa_support : %x\n", ini->video_vesa_support);
+ wfd_sink_debug("video_hh_support : %x\n", ini->video_hh_support);
+ wfd_sink_debug("video_profile : %x\n", ini->video_profile);
+ wfd_sink_debug("video_level : %x\n", ini->video_level);
+ wfd_sink_debug("video_latency : %d\n", ini->video_latency);
+ wfd_sink_debug("video_vertical_resolution : %d\n", ini->video_vertical_resolution);
+ wfd_sink_debug("video_horizontal_resolution : %d\n", ini->video_horizontal_resolution);
+ wfd_sink_debug("video_minimum_slicing : %d\n", ini->video_minimum_slicing);
+ wfd_sink_debug("video_slice_enc_param : %d\n", ini->video_slice_enc_param);
+ wfd_sink_debug("video_framerate_control_support : %d\n", ini->video_framerate_control_support);
+
+ /* hdcp parameter*/
+ wfd_sink_debug("hdcp_content_protection : %x\n", ini->hdcp_content_protection);
+ wfd_sink_debug("hdcp_port_no : %d\n", ini->hdcp_port_no);
+
+ wfd_sink_debug("---------------------------------------------------\n");
+
+ loaded = TRUE;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+
+static
+void __mm_wfd_sink_ini_check_status(void)
+{
+ struct stat ini_buff;
+
+ wfd_sink_debug_fenter();
+
+ if (g_stat(MM_WFD_SINK_INI_DEFAULT_PATH, &ini_buff) < 0) {
+ wfd_sink_error("failed to get mmfw_wfd_sink ini status\n");
+ } else {
+ if (ini_buff.st_size < 5) {
+ wfd_sink_error("mmfw_wfd_sink.ini file size=%d, Corrupted! So, Removed\n", (int)ini_buff.st_size);
+ g_remove(MM_WFD_SINK_INI_DEFAULT_PATH);
+ }
+ }
+
+ wfd_sink_debug_fleave();
+}
+
+int
+mm_wfd_sink_ini_unload(mm_wfd_sink_ini_t *ini)
+{
+ wfd_sink_debug_fenter();
+
+ loaded = FALSE;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
+ * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include "mm_wfd_sink_manager.h"
+
+
+static gpointer __mm_wfd_sink_manager_thread(gpointer data);
+
+int _mm_wfd_sink_init_manager(mm_wfd_sink_t *wfd_sink)
+{
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* create manager mutex */
+ g_mutex_init(&(wfd_sink->manager_thread_mutex));
+
+ /* create capture cond */
+ g_cond_init(&(wfd_sink->manager_thread_cond));
+
+ wfd_sink->manager_thread_cmd = NULL;
+ wfd_sink->manager_thread_exit = FALSE;
+
+ /* create manager thread */
+ wfd_sink->manager_thread =
+ g_thread_new("__mm_wfd_sink_manager_thread", __mm_wfd_sink_manager_thread, (gpointer)wfd_sink);
+ if (wfd_sink->manager_thread == NULL) {
+ wfd_sink_error("failed to create manager thread\n");
+ goto failed_to_init;
+ }
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+failed_to_init:
+ g_mutex_clear(&(wfd_sink->manager_thread_mutex));
+ g_cond_clear(&(wfd_sink->manager_thread_cond));
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+int _mm_wfd_sink_release_manager(mm_wfd_sink_t *wfd_sink)
+{
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* release manager thread */
+ if (wfd_sink->manager_thread) {
+ WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_EXIT);
+ WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
+
+ wfd_sink_debug("waitting for manager thread exit");
+ g_thread_join(wfd_sink->manager_thread);
+ g_mutex_clear(&(wfd_sink->manager_thread_mutex));
+ g_cond_clear(&(wfd_sink->manager_thread_cond));
+ wfd_sink_debug("manager thread released");
+ }
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static gpointer
+__mm_wfd_sink_manager_thread(gpointer data)
+{
+ mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *) data;
+ WFDSinkManagerCMDType cmd = WFD_SINK_MANAGER_CMD_NONE;
+ GList *walk = NULL;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, NULL);
+
+ if (wfd_sink->manager_thread_exit) {
+ wfd_sink_debug("exit manager thread...");
+ return NULL;
+ }
+
+ wfd_sink_debug("manager thread started. waiting for signal");
+
+ while (TRUE) {
+ WFD_SINK_MANAGER_LOCK(wfd_sink);
+ WFD_SINK_MANAGER_WAIT_CMD(wfd_sink);
+
+ for (walk = wfd_sink->manager_thread_cmd; walk; walk = g_list_next(walk)) {
+ cmd = GPOINTER_TO_INT(walk->data);
+
+ wfd_sink_debug("got command %d", cmd);
+
+ switch (cmd) {
+ case WFD_SINK_MANAGER_CMD_LINK_A_DECODEBIN:
+ wfd_sink_debug("try to link audio decodebin.");
+ if (MM_ERROR_NONE != __mm_wfd_sink_link_audio_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to link audio decodebin.....\n");
+ goto EXIT;
+ }
+ break;
+ case WFD_SINK_MANAGER_CMD_LINK_V_DECODEBIN:
+ wfd_sink_debug("try to link video decodebin.");
+ if (MM_ERROR_NONE != __mm_wfd_sink_link_video_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to link video decodebin.....\n");
+ goto EXIT;
+ }
+ break;
+ case WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE:
+ wfd_sink_debug("try to prepare audio pipeline.");
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink)) {
+ wfd_sink_error("failed to prepare audio pipeline.....\n");
+ goto EXIT;
+ }
+ break;
+ case WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE:
+ wfd_sink_debug("try to prepare video pipeline.");
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink)) {
+ wfd_sink_error("failed to prepare video pipeline.....\n");
+ goto EXIT;
+ }
+ break;
+ case WFD_SINK_MANAGER_CMD_EXIT:
+ wfd_sink_debug("exiting manager thread");
+ goto EXIT;
+ break;
+ default:
+ break;
+ }
+ }
+
+ g_list_free(wfd_sink->manager_thread_cmd);
+ wfd_sink->manager_thread_cmd = NULL;
+
+ WFD_SINK_MANAGER_UNLOCK(wfd_sink);
+ }
+
+ wfd_sink_debug_fleave();
+
+ return NULL;
+
+EXIT:
+ wfd_sink->manager_thread_exit = TRUE;
+ g_list_free(wfd_sink->manager_thread_cmd);
+ wfd_sink->manager_thread_cmd = NULL;
+ WFD_SINK_MANAGER_UNLOCK(wfd_sink);
+
+ return NULL;
+}
+
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <gst/gst.h>
+#include <gst/video/videooverlay.h>
+#include <Elementary.h>
+#include <Ecore_Wayland.h>
+
+#include "mm_wfd_sink_util.h"
+#include "mm_wfd_sink_priv.h"
+#include "mm_wfd_sink_manager.h"
+#include "mm_wfd_sink_dlog.h"
+#include "mm_wfd_sink_enum.h"
+#include "mm_wfd_sink_wayland.h"
+
+/* gstreamer */
+static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboolean async);
+
+/* state */
+static int __mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd);
+static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType state);
+
+/* util */
+static void __mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink);
+static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint *CEA_resolution, guint *VESA_resolution, guint *HH_resolution);
+
+int _mm_wfd_sink_create(mm_wfd_sink_t **wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ mm_wfd_sink_t *new_wfd_sink = NULL;
+
+ /* create handle */
+ new_wfd_sink = g_malloc0(sizeof(mm_wfd_sink_t));
+ if (!new_wfd_sink) {
+ wfd_sink_error("failed to allocate memory for wi-fi display sink");
+ return MM_ERROR_WFD_NO_FREE_SPACE;
+ }
+
+ /* Initialize gstreamer related */
+ new_wfd_sink->attrs = 0;
+
+ new_wfd_sink->pipeline = NULL;
+ new_wfd_sink->audio_decodebin_is_linked = FALSE;
+ new_wfd_sink->video_decodebin_is_linked = FALSE;
+
+ /* Initialize timestamp compensation related */
+ new_wfd_sink->need_to_reset_basetime = FALSE;
+ new_wfd_sink->clock = NULL;
+ new_wfd_sink->video_buffer_count = 0LL;
+ new_wfd_sink->video_average_gap = 0LL;
+ new_wfd_sink->video_accumulated_gap = 0LL;
+ new_wfd_sink->audio_buffer_count = 0LL;
+ new_wfd_sink->audio_average_gap = 0LL;
+ new_wfd_sink->audio_accumulated_gap = 0LL;
+ new_wfd_sink->last_buffer_timestamp = GST_CLOCK_TIME_NONE;
+
+ /* Initialize all states */
+ MMWFDSINK_CURRENT_STATE(new_wfd_sink) = MM_WFD_SINK_STATE_NONE;
+ MMWFDSINK_PREVIOUS_STATE(new_wfd_sink) = MM_WFD_SINK_STATE_NONE;
+ MMWFDSINK_PENDING_STATE(new_wfd_sink) = MM_WFD_SINK_STATE_NONE;
+
+ /* initialize audio/video information */
+ new_wfd_sink->stream_info.audio_stream_info.codec = MM_WFD_SINK_AUDIO_CODEC_NONE;
+ new_wfd_sink->stream_info.audio_stream_info.channels = 0;
+ new_wfd_sink->stream_info.audio_stream_info.sample_rate = 0;
+ new_wfd_sink->stream_info.audio_stream_info.bitwidth = 0;
+ new_wfd_sink->stream_info.video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_NONE;
+ new_wfd_sink->stream_info.video_stream_info.width = 0;
+ new_wfd_sink->stream_info.video_stream_info.height = 0;
+ new_wfd_sink->stream_info.video_stream_info.frame_rate = 0;
+
+ /* Initialize command */
+ new_wfd_sink->cmd = MM_WFD_SINK_COMMAND_CREATE;
+ new_wfd_sink->waiting_cmd = FALSE;
+
+ /* Initialize manager related */
+ new_wfd_sink->manager_thread = NULL;
+ new_wfd_sink->manager_thread_cmd = NULL;
+ new_wfd_sink->manager_thread_exit = FALSE;
+
+ /* Initialize video resolution */
+ new_wfd_sink->supportive_resolution = MM_WFD_SINK_RESOLUTION_UNKNOWN;
+
+ /* construct attributes */
+ new_wfd_sink->attrs = _mmwfd_construct_attribute((MMHandleType)new_wfd_sink);
+ if (!new_wfd_sink->attrs) {
+ MMWFDSINK_FREEIF(new_wfd_sink);
+ wfd_sink_error("failed to set attribute");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ /* load ini for initialize */
+ result = mm_wfd_sink_ini_load(&new_wfd_sink->ini);
+ if (result != MM_ERROR_NONE) {
+ wfd_sink_error("failed to load ini file");
+ goto fail_to_load_ini;
+ }
+ new_wfd_sink->need_to_reset_basetime = new_wfd_sink->ini.enable_reset_basetime;
+
+ /* initialize manager */
+ result = _mm_wfd_sink_init_manager(new_wfd_sink);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("failed to init manager : %d", result);
+ goto fail_to_init;
+ }
+
+ /* initialize gstreamer */
+ result = __mm_wfd_sink_init_gstreamer(new_wfd_sink);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("failed to init gstreamer : %d", result);
+ goto fail_to_init;
+ }
+
+ /* set state */
+ __mm_wfd_sink_set_state(new_wfd_sink, MM_WFD_SINK_STATE_NULL);
+
+ /* now take handle */
+ *wfd_sink = new_wfd_sink;
+
+ wfd_sink_debug_fleave();
+
+ return result;
+
+ /* ERRORS */
+fail_to_init:
+ mm_wfd_sink_ini_unload(&new_wfd_sink->ini);
+fail_to_load_ini:
+ _mmwfd_deconstruct_attribute(new_wfd_sink->attrs);
+ MMWFDSINK_FREEIF(new_wfd_sink);
+
+ *wfd_sink = NULL;
+
+ return result;
+}
+
+int _mm_wfd_sink_prepare(mm_wfd_sink_t *wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check current wi-fi display sink state */
+ MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_PREPARE);
+
+ /* construct pipeline */
+ /* create main pipeline */
+ result = __mm_wfd_sink_create_pipeline(wfd_sink);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("failed to create pipeline : %d", result);
+ goto fail_to_create;
+ }
+
+ /* create video decodebin */
+ result = __mm_wfd_sink_create_video_decodebin(wfd_sink);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("failed to create video decodebin %d", result);
+ goto fail_to_create;
+ }
+
+ /* create video sinkbin */
+ result = __mm_wfd_sink_create_video_sinkbin(wfd_sink);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("failed to create video sinkbin %d", result);
+ goto fail_to_create;
+ }
+
+ /* create audio decodebin */
+ result = __mm_wfd_sink_create_audio_decodebin(wfd_sink);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("fail to create audio decodebin : %d", result);
+ goto fail_to_create;
+ }
+
+ /* create audio sinkbin */
+ result = __mm_wfd_sink_create_audio_sinkbin(wfd_sink);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("fail to create audio sinkbin : %d", result);
+ goto fail_to_create;
+ }
+
+ /* set pipeline READY state */
+ result = __mm_wfd_sink_set_pipeline_state(wfd_sink, GST_STATE_READY, TRUE);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("failed to set state : %d", result);
+ goto fail_to_create;
+ }
+
+ /* set state */
+ __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_PREPARED);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+
+ /* ERRORS */
+fail_to_create:
+ /* need to destroy pipeline already created */
+ __mm_wfd_sink_destroy_pipeline(wfd_sink);
+ return result;
+}
+
+int _mm_wfd_sink_connect(mm_wfd_sink_t *wfd_sink, const char *uri)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(uri && strlen(uri) > strlen("rtsp://"), MM_ERROR_WFD_INVALID_ARGUMENT);
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_DEPAY].gst &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_DEMUX].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check current wi-fi display sink state */
+ MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_CONNECT);
+
+ wfd_sink_debug("try to connect to %s.....", GST_STR_NULL(uri));
+
+ /* set uri to wfdsrc */
+ g_object_set(G_OBJECT(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst), "location", uri, NULL);
+
+ /* set pipeline PAUSED state */
+ result = __mm_wfd_sink_set_pipeline_state(wfd_sink, GST_STATE_PAUSED, TRUE);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("failed to set state : %d", result);
+ return result;
+ }
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int _mm_wfd_sink_start(mm_wfd_sink_t *wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check current wi-fi display sink state */
+ MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_START);
+
+ WFD_SINK_MANAGER_LOCK(wfd_sink) ;
+ wfd_sink_debug("check pipeline is ready to start");
+ WFD_SINK_MANAGER_UNLOCK(wfd_sink);
+
+ result = __mm_wfd_sink_set_pipeline_state(wfd_sink, GST_STATE_PLAYING, TRUE);
+ if (result < MM_ERROR_NONE) {
+ wfd_sink_error("failed to set state : %d", result);
+ return result;
+ }
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int _mm_wfd_sink_pause(mm_wfd_sink_t *wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check current wi-fi display sink state */
+ MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_PAUSE);
+
+ g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "pause", NULL);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int _mm_wfd_sink_resume(mm_wfd_sink_t *wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check current wi-fi display sink state */
+ MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_RESUME);
+
+ g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "resume", NULL);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int _mm_wfd_sink_disconnect(mm_wfd_sink_t *wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check current wi-fi display sink state */
+ MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_DISCONNECT);
+
+ WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_EXIT);
+ WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
+
+ g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "close", NULL);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int _mm_wfd_sink_unprepare(mm_wfd_sink_t *wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check current wi-fi display sink state */
+ MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_UNPREPARE);
+
+ WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_EXIT);
+ WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
+
+ /* release pipeline */
+ result = __mm_wfd_sink_destroy_pipeline(wfd_sink);
+ if (result != MM_ERROR_NONE) {
+ wfd_sink_error("failed to destory pipeline");
+ return MM_ERROR_WFD_INTERNAL;
+ } else {
+ wfd_sink_debug("success to destory pipeline");
+ }
+
+ /* set state */
+ __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_NULL);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int _mm_wfd_sink_destroy(mm_wfd_sink_t *wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check current wi-fi display sink state */
+ MMWFDSINK_CHECK_STATE(wfd_sink, MM_WFD_SINK_COMMAND_DESTROY);
+
+ /* unload ini */
+ mm_wfd_sink_ini_unload(&wfd_sink->ini);
+
+ /* release attributes */
+ _mmwfd_deconstruct_attribute(wfd_sink->attrs);
+
+ if (MM_ERROR_NONE != _mm_wfd_sink_release_manager(wfd_sink)) {
+ wfd_sink_error("failed to release manager");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+
+ /* set state */
+ __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_NONE);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+int _mm_wfd_set_message_callback(mm_wfd_sink_t *wfd_sink, MMWFDMessageCallback callback, void *user_data)
+{
+ int result = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ wfd_sink->msg_cb = callback;
+ wfd_sink->msg_user_data = user_data;
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+static int __mm_wfd_sink_init_gstreamer(mm_wfd_sink_t *wfd_sink)
+{
+ int result = MM_ERROR_NONE;
+ gint *argc = NULL;
+ gchar **argv = NULL;
+ static const int max_argc = 50;
+ GError *err = NULL;
+ gint i = 0;
+
+ wfd_sink_debug_fenter();
+
+ /* alloc */
+ argc = calloc(1, sizeof(gint));
+ argv = calloc(max_argc, sizeof(gchar *));
+ if (!argc || !argv) {
+ wfd_sink_error("failed to allocate memory for wfdsink");
+
+ MMWFDSINK_FREEIF(argv);
+ MMWFDSINK_FREEIF(argc);
+
+ return MM_ERROR_WFD_NO_FREE_SPACE;
+ }
+
+ /* we would not do fork for scanning plugins */
+ argv[*argc] = g_strdup("--gst-disable-registry-fork");
+ (*argc)++;
+
+ /* check disable registry scan */
+ argv[*argc] = g_strdup("--gst-disable-registry-update");
+ (*argc)++;
+
+ /* check disable segtrap */
+ argv[*argc] = g_strdup("--gst-disable-segtrap");
+ (*argc)++;
+
+ /* check ini */
+ for (i = 0; i < 5; i++) {
+ if (strlen(wfd_sink->ini.gst_param[i]) > 2) {
+ wfd_sink_debug("set %s", wfd_sink->ini.gst_param[i]);
+ argv[*argc] = g_strdup(wfd_sink->ini.gst_param[i]);
+ (*argc)++;
+ }
+ }
+
+ wfd_sink_debug("initializing gstreamer with following parameter");
+ wfd_sink_debug("argc : %d", *argc);
+
+ for (i = 0; i < *argc; i++) {
+ wfd_sink_debug("argv[%d] : %s", i, argv[i]);
+ }
+
+ /* initializing gstreamer */
+ if (!gst_init_check(argc, &argv, &err)) {
+ wfd_sink_error("failed to initialize gstreamer: %s", err ? err->message : "unknown error occurred");
+ if (err)
+ g_error_free(err);
+
+ result = MM_ERROR_WFD_INTERNAL;
+ }
+
+ /* release */
+ for (i = 0; i < *argc; i++) {
+ MMWFDSINK_FREEIF(argv[i]);
+ }
+ MMWFDSINK_FREEIF(argv);
+ MMWFDSINK_FREEIF(argc);
+
+ wfd_sink_debug_fleave();
+
+ return result;
+}
+
+static GstBusSyncReply
+_mm_wfd_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data)
+{
+ GstBusSyncReply ret = GST_BUS_PASS;
+
+ wfd_sink_return_val_if_fail(message &&
+ GST_IS_MESSAGE(message) &&
+ GST_MESSAGE_SRC(message),
+ GST_BUS_DROP);
+
+ switch (GST_MESSAGE_TYPE(message)) {
+ case GST_MESSAGE_TAG:
+ break;
+ case GST_MESSAGE_DURATION:
+ break;
+ case GST_MESSAGE_STATE_CHANGED: {
+ /* we only handle state change messages from pipeline */
+ if (!GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
+ ret = GST_BUS_DROP;
+ }
+ break;
+ case GST_MESSAGE_ASYNC_DONE: {
+ if (!GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
+ ret = GST_BUS_DROP;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static gboolean
+_mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
+{
+ mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *) data;
+ const GstStructure *message_structure = gst_message_get_structure(msg);
+ gboolean ret = TRUE;
+
+ wfd_sink_return_val_if_fail(wfd_sink, FALSE);
+ wfd_sink_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE);
+
+ wfd_sink_debug("got %s from %s",
+ GST_STR_NULL(GST_MESSAGE_TYPE_NAME(msg)),
+ GST_STR_NULL(GST_OBJECT_NAME(GST_MESSAGE_SRC(msg))));
+
+ switch (GST_MESSAGE_TYPE(msg)) {
+ case GST_MESSAGE_ERROR: {
+ GError *error = NULL;
+ gchar *debug = NULL;
+
+ /* get error code */
+ gst_message_parse_error(msg, &error, &debug);
+
+ wfd_sink_error("error : %s", error->message);
+ wfd_sink_error("debug : %s", debug);
+
+ MMWFDSINK_FREEIF(debug);
+ g_error_free(error);
+ }
+ break;
+
+ case GST_MESSAGE_WARNING: {
+ char *debug = NULL;
+ GError *error = NULL;
+
+ gst_message_parse_warning(msg, &error, &debug);
+
+ wfd_sink_warning("warning : %s", error->message);
+ wfd_sink_warning("debug : %s", debug);
+
+ MMWFDSINK_FREEIF(debug);
+ g_error_free(error);
+ }
+ break;
+
+ case GST_MESSAGE_STATE_CHANGED: {
+ const GValue *voldstate, *vnewstate, *vpending;
+ GstState oldstate, newstate, pending;
+ const GstStructure *structure;
+
+ /* we only handle messages from pipeline */
+ if (msg->src != (GstObject *)wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst)
+ break;
+
+ /* get state info from msg */
+ structure = gst_message_get_structure(msg);
+ if (structure == NULL)
+ break;
+
+ voldstate = gst_structure_get_value(structure, "old-state");
+ vnewstate = gst_structure_get_value(structure, "new-state");
+ vpending = gst_structure_get_value(structure, "pending-state");
+ if (voldstate == NULL || vnewstate == NULL || vpending == NULL)
+ break;
+
+ oldstate = (GstState)voldstate->data[0].v_int;
+ newstate = (GstState)vnewstate->data[0].v_int;
+ pending = (GstState)vpending->data[0].v_int;
+
+ wfd_sink_debug("state changed [%s] : %s--->%s final : %s",
+ GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
+ gst_element_state_get_name((GstState)oldstate),
+ gst_element_state_get_name((GstState)newstate),
+ gst_element_state_get_name((GstState)pending));
+
+ if (oldstate == newstate) {
+ wfd_sink_debug("pipeline reports state transition to old state");
+ break;
+ }
+
+ switch (newstate) {
+ case GST_STATE_VOID_PENDING:
+ case GST_STATE_NULL:
+ case GST_STATE_READY:
+ case GST_STATE_PAUSED:
+ case GST_STATE_PLAYING:
+ default:
+ break;
+ }
+ }
+ break;
+
+ case GST_MESSAGE_CLOCK_LOST: {
+ GstClock *clock = NULL;
+ gst_message_parse_clock_lost(msg, &clock);
+ wfd_sink_debug("The current clock[%s] as selected by the pipeline became unusable.", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
+ }
+ break;
+
+ case GST_MESSAGE_NEW_CLOCK: {
+ GstClock *clock = NULL;
+ gst_message_parse_new_clock(msg, &clock);
+ if (!clock)
+ break;
+
+ if (wfd_sink->clock) {
+ if (wfd_sink->clock != clock)
+ wfd_sink_debug("clock is changed! [%s] -->[%s]",
+ GST_STR_NULL(GST_OBJECT_NAME(wfd_sink->clock)),
+ GST_STR_NULL(GST_OBJECT_NAME(clock)));
+ else
+ wfd_sink_debug("same clock is selected again! [%s]",
+ GST_STR_NULL(GST_OBJECT_NAME(clock)));
+ } else {
+ wfd_sink_debug("new clock [%s] was selected in the pipeline",
+ (GST_STR_NULL(GST_OBJECT_NAME(clock))));
+ }
+
+ wfd_sink->clock = clock;
+ }
+ break;
+
+ case GST_MESSAGE_APPLICATION: {
+ const gchar *message_structure_name;
+
+ message_structure_name = gst_structure_get_name(message_structure);
+ if (!message_structure_name)
+ break;
+
+ wfd_sink_debug("message name : %s", GST_STR_NULL(message_structure_name));
+ }
+ break;
+
+ case GST_MESSAGE_ELEMENT: {
+ const gchar *structure_name = NULL;
+
+ structure_name = gst_structure_get_name(message_structure);
+ if (structure_name) {
+ wfd_sink_debug("got element specific message[%s]", GST_STR_NULL(structure_name));
+ if (g_strrstr(structure_name, "GstUDPSrcTimeout")) {
+ wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+ } else if (g_strrstr(structure_name, "GstWFDSrcSessionTimeout")) {
+ wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+ }
+ }
+ }
+ break;
+
+ case GST_MESSAGE_PROGRESS: {
+ GstProgressType type = GST_PROGRESS_TYPE_ERROR;
+ gchar *category = NULL, *text = NULL;
+
+ gst_message_parse_progress(msg, &type, &category, &text);
+ wfd_sink_debug("%s : %s ", GST_STR_NULL(category), GST_STR_NULL(text));
+
+ switch (type) {
+ case GST_PROGRESS_TYPE_START:
+ break;
+ case GST_PROGRESS_TYPE_COMPLETE:
+ if (category && !strcmp(category, "open"))
+ __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_CONNECTED);
+ else if (category && !strcmp(category, "play")) {
+ __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_PLAYING);
+ /*_mm_wfd_sink_correct_pipeline_latency (wfd_sink); */
+ } else if (category && !strcmp(category, "pause"))
+ __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_PAUSED);
+ else if (category && !strcmp(category, "close"))
+ __mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_DISCONNECTED);
+ break;
+ case GST_PROGRESS_TYPE_CANCELED:
+ break;
+ case GST_PROGRESS_TYPE_ERROR:
+ if (category && !strcmp(category, "open")) {
+ wfd_sink_error("got error : %s", GST_STR_NULL(text));
+ /*_mm_wfd_sink_disconnect (wfd_sink); */
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+ } else if (category && !strcmp(category, "play")) {
+ wfd_sink_error("got error : %s", GST_STR_NULL(text));
+ /*_mm_wfd_sink_disconnect (wfd_sink); */
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+ } else if (category && !strcmp(category, "pause")) {
+ wfd_sink_error("got error : %s", GST_STR_NULL(text));
+ /*_mm_wfd_sink_disconnect (wfd_sink); */
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+ } else if (category && !strcmp(category, "close")) {
+ wfd_sink_error("got error : %s", GST_STR_NULL(text));
+ /*_mm_wfd_sink_disconnect (wfd_sink); */
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+ } else {
+ wfd_sink_error("got error : %s", GST_STR_NULL(text));
+ }
+ break;
+ default:
+ wfd_sink_error("progress message has no type");
+ return ret;
+ }
+
+ MMWFDSINK_FREEIF(category);
+ MMWFDSINK_FREEIF(text);
+ }
+ break;
+ case GST_MESSAGE_ASYNC_START:
+ wfd_sink_debug("GST_MESSAGE_ASYNC_START : %s", gst_element_get_name(GST_MESSAGE_SRC(msg)));
+ break;
+ case GST_MESSAGE_ASYNC_DONE:
+ wfd_sink_debug("GST_MESSAGE_ASYNC_DONE : %s", gst_element_get_name(GST_MESSAGE_SRC(msg)));
+ break;
+ case GST_MESSAGE_UNKNOWN:
+ case GST_MESSAGE_INFO:
+ case GST_MESSAGE_TAG:
+ case GST_MESSAGE_BUFFERING:
+ case GST_MESSAGE_EOS:
+ case GST_MESSAGE_STATE_DIRTY:
+ case GST_MESSAGE_STEP_DONE:
+ case GST_MESSAGE_CLOCK_PROVIDE:
+ case GST_MESSAGE_STRUCTURE_CHANGE:
+ case GST_MESSAGE_STREAM_STATUS:
+ case GST_MESSAGE_SEGMENT_START:
+ case GST_MESSAGE_SEGMENT_DONE:
+ case GST_MESSAGE_DURATION:
+ case GST_MESSAGE_LATENCY:
+ case GST_MESSAGE_REQUEST_STATE:
+ case GST_MESSAGE_STEP_START:
+ case GST_MESSAGE_QOS:
+ case GST_MESSAGE_ANY:
+ break;
+ default:
+ wfd_sink_debug("unhandled message");
+ break;
+ }
+
+ return ret;
+}
+
+static int
+__mm_wfd_sink_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket, gboolean need_prepare)
+{
+ GList *bucket = element_bucket;
+ MMWFDSinkGstElement *element = NULL;
+ int successful_add_count = 0;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(element_bucket, 0);
+ wfd_sink_return_val_if_fail(bin, 0);
+
+ for (; bucket; bucket = bucket->next) {
+ element = (MMWFDSinkGstElement *)bucket->data;
+
+ if (element && element->gst) {
+ if (need_prepare)
+ gst_element_set_state(GST_ELEMENT(element->gst), GST_STATE_READY);
+
+ if (!gst_bin_add(GST_BIN(bin), GST_ELEMENT(element->gst))) {
+ wfd_sink_error("failed to add element [%s] to bin [%s]",
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
+ return 0;
+ }
+
+ wfd_sink_debug("add element [%s] to bin [%s]",
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
+
+ successful_add_count++;
+ }
+ }
+
+ wfd_sink_debug_fleave();
+
+ return successful_add_count;
+}
+
+static int
+__mm_wfd_sink_gst_element_link_bucket(GList *element_bucket)
+{
+ GList *bucket = element_bucket;
+ MMWFDSinkGstElement *element = NULL;
+ MMWFDSinkGstElement *prv_element = NULL;
+ gint successful_link_count = 0;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(element_bucket, -1);
+
+ prv_element = (MMWFDSinkGstElement *)bucket->data;
+ bucket = bucket->next;
+
+ for (; bucket; bucket = bucket->next) {
+ element = (MMWFDSinkGstElement *)bucket->data;
+
+ if (element && element->gst) {
+ if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
+ wfd_sink_debug("linking [%s] to [%s] success",
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
+ successful_link_count++;
+ } else {
+ wfd_sink_error("linking [%s] to [%s] failed",
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
+ return -1;
+ }
+ }
+
+ prv_element = element;
+ }
+
+ wfd_sink_debug_fleave();
+
+ return successful_link_count;
+}
+
+static int
+__mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd)
+{
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_PRINT_STATE(wfd_sink);
+
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
+
+ switch (cmd) {
+ case MM_WFD_SINK_COMMAND_CREATE: {
+ if (cur_state != MM_WFD_SINK_STATE_NONE)
+ goto invalid_state;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NULL;
+ }
+ break;
+
+ case MM_WFD_SINK_COMMAND_PREPARE: {
+ if (cur_state == MM_WFD_SINK_STATE_PREPARED)
+ goto no_operation;
+ else if (cur_state != MM_WFD_SINK_STATE_NULL)
+ goto invalid_state;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PREPARED;
+ }
+ break;
+
+ case MM_WFD_SINK_COMMAND_CONNECT: {
+ if (cur_state == MM_WFD_SINK_STATE_CONNECTED)
+ goto no_operation;
+ else if (cur_state != MM_WFD_SINK_STATE_PREPARED)
+ goto invalid_state;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_CONNECTED;
+ }
+ break;
+
+ case MM_WFD_SINK_COMMAND_START: {
+ if (cur_state == MM_WFD_SINK_STATE_PLAYING)
+ goto no_operation;
+ else if (cur_state != MM_WFD_SINK_STATE_CONNECTED)
+ goto invalid_state;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PLAYING;
+ }
+ break;
+
+ case MM_WFD_SINK_COMMAND_PAUSE: {
+ if (cur_state == MM_WFD_SINK_STATE_PAUSED)
+ goto no_operation;
+ else if (cur_state != MM_WFD_SINK_STATE_PLAYING)
+ goto invalid_state;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PAUSED;
+ }
+ break;
+
+ case MM_WFD_SINK_COMMAND_RESUME: {
+ if (cur_state == MM_WFD_SINK_STATE_PLAYING)
+ goto no_operation;
+ else if (cur_state != MM_WFD_SINK_STATE_PAUSED)
+ goto invalid_state;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_PLAYING;
+ }
+ break;
+
+ case MM_WFD_SINK_COMMAND_DISCONNECT: {
+ if (cur_state == MM_WFD_SINK_STATE_NONE ||
+ cur_state == MM_WFD_SINK_STATE_NULL ||
+ cur_state == MM_WFD_SINK_STATE_PREPARED ||
+ cur_state == MM_WFD_SINK_STATE_DISCONNECTED)
+ goto no_operation;
+ else if (cur_state != MM_WFD_SINK_STATE_PLAYING &&
+ cur_state != MM_WFD_SINK_STATE_CONNECTED &&
+ cur_state != MM_WFD_SINK_STATE_PAUSED)
+ goto invalid_state;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_DISCONNECTED;
+ }
+ break;
+
+ case MM_WFD_SINK_COMMAND_UNPREPARE: {
+ if (cur_state == MM_WFD_SINK_STATE_NONE ||
+ cur_state == MM_WFD_SINK_STATE_NULL)
+ goto no_operation;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NULL;
+ }
+ break;
+
+ case MM_WFD_SINK_COMMAND_DESTROY: {
+ if (cur_state == MM_WFD_SINK_STATE_NONE)
+ goto no_operation;
+
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ wfd_sink->cmd = cmd;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+no_operation:
+ wfd_sink_debug("already %s state, nothing to do.", MMWFDSINK_STATE_GET_NAME(cur_state));
+ return MM_ERROR_WFD_NO_OP;
+
+ /* ERRORS */
+invalid_state:
+ wfd_sink_error("current state is invalid.", MMWFDSINK_STATE_GET_NAME(cur_state));
+ return MM_ERROR_WFD_INVALID_STATE;
+}
+
+static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType state)
+{
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (MMWFDSINK_CURRENT_STATE(wfd_sink) == state) {
+ wfd_sink_error("already state(%s)", MMWFDSINK_STATE_GET_NAME(state));
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
+ return MM_ERROR_NONE;
+ }
+
+ /* update wi-fi display state */
+ MMWFDSINK_PREVIOUS_STATE(wfd_sink) = MMWFDSINK_CURRENT_STATE(wfd_sink);
+ MMWFDSINK_CURRENT_STATE(wfd_sink) = state;
+
+ if (MMWFDSINK_CURRENT_STATE(wfd_sink) == MMWFDSINK_PENDING_STATE(wfd_sink))
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
+
+ /* poset state message to application */
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_NONE,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+
+ /* print state */
+ MMWFDSINK_PRINT_STATE(wfd_sink);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int
+__mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboolean async)
+{
+ GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
+ GstState cur_state = GST_STATE_VOID_PENDING;
+ GstState pending_state = GST_STATE_VOID_PENDING;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ wfd_sink_return_val_if_fail(state > GST_STATE_VOID_PENDING, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+ wfd_sink_debug("try to set %s state ", gst_element_state_get_name(state));
+
+ result = gst_element_set_state(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst, state);
+ if (result == GST_STATE_CHANGE_FAILURE) {
+ wfd_sink_error("fail to set %s state....", gst_element_state_get_name(state));
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ if (!async) {
+ wfd_sink_debug("wait for changing state is completed ");
+
+ result = gst_element_get_state(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst, &cur_state, &pending_state, wfd_sink->ini.state_change_timeout * GST_SECOND);
+ if (result == GST_STATE_CHANGE_FAILURE) {
+ wfd_sink_error("fail to get state within %d seconds....", wfd_sink->ini.state_change_timeout);
+
+ __mm_wfd_sink_dump_pipeline_state(wfd_sink);
+
+ return MM_ERROR_WFD_INTERNAL;
+ } else if (result == GST_STATE_CHANGE_NO_PREROLL) {
+ wfd_sink_debug("successfully changed state but is not able to provide data yet");
+ }
+
+ wfd_sink_debug("cur state is %s, pending state is %s",
+ gst_element_state_get_name(cur_state),
+ gst_element_state_get_name(pending_state));
+ }
+
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static void
+_mm_wfd_sink_reset_basetime(mm_wfd_sink_t *wfd_sink)
+{
+ GstClockTime base_time = GST_CLOCK_TIME_NONE;
+ int i;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+ wfd_sink_return_if_fail(wfd_sink->need_to_reset_basetime);
+
+
+ if (wfd_sink->clock)
+ base_time = gst_clock_get_time(wfd_sink->clock);
+
+ if (GST_CLOCK_TIME_IS_VALID(base_time)) {
+
+ wfd_sink_debug("set pipeline base_time as now [%"GST_TIME_FORMAT"]", GST_TIME_ARGS(base_time));
+
+ for (i = 0; i < WFD_SINK_M_NUM; i++) {
+ if (wfd_sink->pipeline->mainbin[i].gst)
+ gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->mainbin[i].gst), base_time);
+ }
+
+ if (wfd_sink->pipeline->v_decodebin) {
+ for (i = 0; i < WFD_SINK_V_D_NUM; i++) {
+ if (wfd_sink->pipeline->v_decodebin[i].gst)
+ gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->v_decodebin[i].gst), base_time);
+ }
+ }
+
+ if (wfd_sink->pipeline->v_sinkbin) {
+ for (i = 0; i < WFD_SINK_V_S_NUM; i++) {
+ if (wfd_sink->pipeline->v_sinkbin[i].gst)
+ gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->v_sinkbin[i].gst), base_time);
+ }
+ }
+
+ if (wfd_sink->pipeline->a_decodebin) {
+ for (i = 0; i < WFD_SINK_A_D_NUM; i++) {
+ if (wfd_sink->pipeline->a_decodebin[i].gst)
+ gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->a_decodebin[i].gst), base_time);
+ }
+ }
+
+ if (wfd_sink->pipeline->a_sinkbin) {
+ for (i = 0; i < WFD_SINK_A_S_NUM; i++) {
+ if (wfd_sink->pipeline->a_sinkbin[i].gst)
+ gst_element_set_base_time(GST_ELEMENT_CAST(wfd_sink->pipeline->a_sinkbin[i].gst), base_time);
+ }
+ }
+
+ wfd_sink->need_to_reset_basetime = FALSE;
+ }
+
+ wfd_sink_debug_fleave();
+
+ return;
+}
+
+int
+__mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+ GstElement *bin = NULL;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check video decodebin is linked */
+ if (!wfd_sink->video_decodebin_is_linked) {
+ /* check video decodebin is created */
+ if (wfd_sink->pipeline->v_decodebin == NULL) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_create_video_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to create video decodebin....");
+ goto ERROR;
+ }
+ }
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_link_video_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to link video decodebin.....");
+ goto ERROR;
+ }
+ }
+
+ /* check video sinkbin is created */
+ if (wfd_sink->pipeline->v_sinkbin == NULL) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_create_video_sinkbin(wfd_sink)) {
+ wfd_sink_error("failed to create video sinkbin....");
+ goto ERROR;
+ }
+ }
+
+ /* set video decodebin state as READY */
+ if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+ bin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+ if (GST_STATE(bin) <= GST_STATE_NULL) {
+ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
+ wfd_sink_error("failed to set state(READY) to video decodebin");
+ goto ERROR;
+ }
+ }
+ } else {
+ wfd_sink_warning("going on without video decodebin....");
+ }
+
+ /* set video sinkbin state as READY */
+ if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+ bin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+ if (GST_STATE(bin) <= GST_STATE_NULL) {
+ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
+ wfd_sink_error("failed to set state(READY) to video sinkbin");
+ goto ERROR;
+ }
+ }
+ } else {
+ wfd_sink_warning("going on without video sinkbin....");
+ }
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+ /* ERRORS */
+ERROR:
+ /* need to notify to app */
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+ GstElement *bin = NULL;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check audio decodebin is linked */
+ if (!wfd_sink->audio_decodebin_is_linked) {
+ /* check audio decodebin is created */
+ if (wfd_sink->pipeline->a_decodebin == NULL) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_create_audio_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to create audio decodebin....");
+ goto ERROR;
+ }
+ }
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_link_audio_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to link audio decodebin.....");
+ goto ERROR;
+ }
+ }
+
+ /* check audio sinkbin is created */
+ if (wfd_sink->pipeline->a_sinkbin == NULL) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_create_audio_sinkbin(wfd_sink)) {
+ wfd_sink_error("failed to create audio sinkbin....");
+ goto ERROR;
+ }
+ }
+
+ /* set audio decodebin state as READY */
+ if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
+ bin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+ if (GST_STATE(bin) <= GST_STATE_NULL) {
+ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin, GST_STATE_READY)) {
+ wfd_sink_error("failed to set state(READY) to audio decodebin");
+ goto ERROR;
+ }
+ }
+ } else {
+ wfd_sink_warning("going on without audio decodebin....");
+ }
+
+ /* set audio sinkbin state as READY */
+ if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+ bin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+ if (GST_STATE(bin) <= GST_STATE_NULL) {
+ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(bin , GST_STATE_READY)) {
+ wfd_sink_error("failed to set state(READY) to audio sinkbin");
+ goto ERROR;
+ }
+ }
+ } else {
+ wfd_sink_warning("going on without audio sinkbin....");
+ }
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+ /* ERRORS */
+ERROR:
+ /* need to notify to app */
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+#define COMPENSATION_CRETERIA_VALUE 1000000 /* 1 msec */
+#define COMPENSATION_CHECK_PERIOD (30*GST_SECOND) /* 30 sec */
+
+static GstPadProbeReturn
+_mm_wfd_sink_check_running_time(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
+{
+ mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)u_data;
+ GstClockTime current_time = GST_CLOCK_TIME_NONE;
+ GstClockTime start_time = GST_CLOCK_TIME_NONE;
+ GstClockTime running_time = GST_CLOCK_TIME_NONE;
+ GstClockTime base_time = GST_CLOCK_TIME_NONE;
+ GstClockTime render_time = GST_CLOCK_TIME_NONE;
+ GstClockTimeDiff diff = GST_CLOCK_TIME_NONE;
+ GstBuffer *buffer = NULL;
+ gint64 ts_offset = 0LL;
+
+ wfd_sink_return_val_if_fail(info, FALSE);
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+ GST_PAD_PROBE_DROP);
+
+ if (!wfd_sink->clock) {
+ wfd_sink_warning("pipeline did not select clock, yet");
+ return GST_PAD_PROBE_OK;
+ }
+
+ if (wfd_sink->need_to_reset_basetime)
+ _mm_wfd_sink_reset_basetime(wfd_sink);
+
+ /* calculate current runninig time */
+ current_time = gst_clock_get_time(wfd_sink->clock);
+ if (g_strrstr(GST_OBJECT_NAME(pad), "video"))
+ base_time = gst_element_get_base_time(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst);
+ else if (g_strrstr(GST_OBJECT_NAME(pad), "audio"))
+ base_time = gst_element_get_base_time(wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst);
+ start_time = gst_element_get_start_time(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+ if (GST_CLOCK_TIME_IS_VALID(current_time) &&
+ GST_CLOCK_TIME_IS_VALID(start_time) &&
+ GST_CLOCK_TIME_IS_VALID(base_time)) {
+ running_time = current_time - (start_time + base_time);
+ } else {
+ wfd_sink_debug("current time %"GST_TIME_FORMAT", start time %"GST_TIME_FORMAT
+ " base time %"GST_TIME_FORMAT"", GST_TIME_ARGS(current_time),
+ GST_TIME_ARGS(start_time), GST_TIME_ARGS(base_time));
+ return GST_PAD_PROBE_OK;
+ }
+
+ /* calculate this buffer rendering time */
+ buffer = gst_pad_probe_info_get_buffer(info);
+ if (!GST_BUFFER_TIMESTAMP_IS_VALID(buffer)) {
+ wfd_sink_warning("buffer timestamp is invalid.");
+ return GST_PAD_PROBE_OK;
+ }
+
+ if (g_strrstr(GST_OBJECT_NAME(pad), "audio")) {
+ if (wfd_sink->pipeline && wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst)
+ g_object_get(G_OBJECT(wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst), "ts-offset", &ts_offset, NULL);
+ } else if (g_strrstr(GST_OBJECT_NAME(pad), "video")) {
+ if (wfd_sink->pipeline && wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst)
+ g_object_get(G_OBJECT(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst), "ts-offset", &ts_offset, NULL);
+ }
+
+ render_time = GST_BUFFER_TIMESTAMP(buffer);
+ render_time += ts_offset;
+
+ /* chekc this buffer could be rendered or not */
+ if (GST_CLOCK_TIME_IS_VALID(running_time) && GST_CLOCK_TIME_IS_VALID(render_time)) {
+ diff = GST_CLOCK_DIFF(running_time, render_time);
+ if (diff < 0) {
+ /* this buffer could be NOT rendered */
+ wfd_sink_debug("%s : diff time : -%" GST_TIME_FORMAT "",
+ GST_STR_NULL((GST_OBJECT_NAME(pad))),
+ GST_TIME_ARGS(GST_CLOCK_DIFF(render_time, running_time)));
+ } else {
+ /* this buffer could be rendered */
+ /*wfd_sink_debug ("%s :diff time : %" GST_TIME_FORMAT "\n", */
+ /* GST_STR_NULL((GST_OBJECT_NAME(pad))), */
+ /* GST_TIME_ARGS(diff)); */
+ }
+ }
+
+ /* update buffer count and gap */
+ if (g_strrstr(GST_OBJECT_NAME(pad), "video")) {
+ wfd_sink->video_buffer_count++;
+ wfd_sink->video_accumulated_gap += diff;
+ } else if (g_strrstr(GST_OBJECT_NAME(pad), "audio")) {
+ wfd_sink->audio_buffer_count++;
+ wfd_sink->audio_accumulated_gap += diff;
+ } else {
+ wfd_sink_warning("invalid buffer type.. ");
+ return GST_PAD_PROBE_DROP;
+ }
+
+ if (GST_CLOCK_TIME_IS_VALID(wfd_sink->last_buffer_timestamp)) {
+ /* fisrt 60sec, just calculate the gap between source device and sink device */
+ if (GST_BUFFER_TIMESTAMP(buffer) < 60 * GST_SECOND)
+ return GST_PAD_PROBE_OK;
+
+ /* every 10sec, calculate the gap between source device and sink device */
+ if (GST_CLOCK_DIFF(wfd_sink->last_buffer_timestamp, GST_BUFFER_TIMESTAMP(buffer))
+ > COMPENSATION_CHECK_PERIOD) {
+ gint64 audio_avgrage_gap = 0LL;
+ gint64 video_avgrage_gap = 0LL;
+ gint64 audio_avgrage_gap_diff = 0LL;
+ gint64 video_avgrage_gap_diff = 0LL;
+ gboolean video_minus_compensation = FALSE;
+ gboolean audio_minus_compensation = FALSE;
+ gint64 avgrage_gap_diff = 0LL;
+ gboolean minus_compensation = FALSE;
+
+ /* check video */
+ if (wfd_sink->video_buffer_count > 0) {
+ video_avgrage_gap = wfd_sink->video_accumulated_gap / wfd_sink->video_buffer_count;
+
+ if (wfd_sink->video_average_gap != 0) {
+ if (video_avgrage_gap > wfd_sink->video_average_gap) {
+ video_avgrage_gap_diff = video_avgrage_gap - wfd_sink->video_average_gap;
+ video_minus_compensation = TRUE;
+ } else {
+ video_avgrage_gap_diff = wfd_sink->video_average_gap - video_avgrage_gap;
+ video_minus_compensation = FALSE;
+ }
+ } else {
+ wfd_sink_debug("first update video average gap(%lld) ", video_avgrage_gap);
+ wfd_sink->video_average_gap = video_avgrage_gap;
+ }
+ } else {
+ wfd_sink_debug("there is no video buffer flow during %"GST_TIME_FORMAT
+ " ~ %" GST_TIME_FORMAT"",
+ GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
+ GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+ }
+
+ /* check audio */
+ if (wfd_sink->audio_buffer_count > 0) {
+ audio_avgrage_gap = wfd_sink->audio_accumulated_gap / wfd_sink->audio_buffer_count;
+
+ if (wfd_sink->audio_average_gap != 0) {
+ if (audio_avgrage_gap > wfd_sink->audio_average_gap) {
+ audio_avgrage_gap_diff = audio_avgrage_gap - wfd_sink->audio_average_gap;
+ audio_minus_compensation = TRUE;
+ } else {
+ audio_avgrage_gap_diff = wfd_sink->audio_average_gap - audio_avgrage_gap;
+ audio_minus_compensation = FALSE;
+ }
+ } else {
+ wfd_sink_debug("first update audio average gap(%lld) ", audio_avgrage_gap);
+ wfd_sink->audio_average_gap = audio_avgrage_gap;
+ }
+ } else {
+ wfd_sink_debug("there is no audio buffer flow during %"GST_TIME_FORMAT
+ " ~ %" GST_TIME_FORMAT"",
+ GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
+ GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+ }
+
+ /* selecet average_gap_diff between video and audio */
+ /* which makes no buffer drop in the sink elements */
+ if (video_avgrage_gap_diff && audio_avgrage_gap_diff) {
+ if (!video_minus_compensation && !audio_minus_compensation) {
+ minus_compensation = FALSE;
+ if (video_avgrage_gap_diff > audio_avgrage_gap_diff)
+ avgrage_gap_diff = video_avgrage_gap_diff;
+ else
+ avgrage_gap_diff = audio_avgrage_gap_diff;
+ } else if (video_minus_compensation && audio_minus_compensation) {
+ minus_compensation = TRUE;
+ if (video_avgrage_gap_diff > audio_avgrage_gap_diff)
+ avgrage_gap_diff = audio_avgrage_gap_diff;
+ else
+ avgrage_gap_diff = video_avgrage_gap_diff;
+ } else {
+ minus_compensation = FALSE;
+ if (!video_minus_compensation)
+ avgrage_gap_diff = video_avgrage_gap_diff;
+ else
+ avgrage_gap_diff = audio_avgrage_gap_diff;
+ }
+ } else if (video_avgrage_gap_diff) {
+ minus_compensation = video_minus_compensation;
+ avgrage_gap_diff = video_avgrage_gap_diff;
+ } else if (audio_avgrage_gap_diff) {
+ minus_compensation = audio_minus_compensation;
+ avgrage_gap_diff = audio_avgrage_gap_diff;
+ }
+
+ wfd_sink_debug("average diff gap difference beween audio:%s%lld and video:%s%lld ",
+ audio_minus_compensation ? "-" : "", audio_avgrage_gap_diff,
+ video_minus_compensation ? "-" : "", video_avgrage_gap_diff);
+
+
+ /* if calculated gap diff is larger than 1ms. need to compensate buffer timestamp */
+ if (avgrage_gap_diff >= COMPENSATION_CRETERIA_VALUE) {
+ if (minus_compensation)
+ ts_offset -= avgrage_gap_diff;
+ else
+ ts_offset += avgrage_gap_diff;
+
+ wfd_sink_debug("do timestamp compensation : %s%lld (ts-offset : %"
+ GST_TIME_FORMAT") at(%" GST_TIME_FORMAT")",
+ minus_compensation ? "-" : "", avgrage_gap_diff,
+ GST_TIME_ARGS(ts_offset), GST_TIME_ARGS(running_time));
+
+ if (wfd_sink->pipeline && wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst)
+ g_object_set(G_OBJECT(wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_SINK].gst), "ts-offset", (gint64)ts_offset, NULL);
+ if (wfd_sink->pipeline && wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst)
+ g_object_set(G_OBJECT(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst), "ts-offset", (gint64)ts_offset, NULL);
+ } else {
+ wfd_sink_debug("don't need to do timestamp compensation : %s%lld (ts-offset : %"GST_TIME_FORMAT ")",
+ minus_compensation ? "-" : "", avgrage_gap_diff, GST_TIME_ARGS(ts_offset));
+ }
+
+ /* reset values*/
+ wfd_sink->video_buffer_count = 0;
+ wfd_sink->video_accumulated_gap = 0LL;
+ wfd_sink->audio_buffer_count = 0;
+ wfd_sink->audio_accumulated_gap = 0LL;
+ wfd_sink->last_buffer_timestamp = GST_BUFFER_TIMESTAMP(buffer);
+ }
+ } else {
+ wfd_sink_debug("first update last buffer timestamp :%" GST_TIME_FORMAT,
+ GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+ wfd_sink->last_buffer_timestamp = GST_BUFFER_TIMESTAMP(buffer);
+ }
+
+ return GST_PAD_PROBE_OK;
+}
+
+
+static void
+__mm_wfd_sink_demux_pad_added(GstElement *ele, GstPad *pad, gpointer data)
+{
+ mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
+ gchar *name = gst_pad_get_name(pad);
+ GstElement *pipeline = NULL;
+ GstElement *decodebin = NULL;
+ GstElement *sinkbin = NULL;
+ GstPad *sinkpad = NULL;
+ GstPad *srcpad = NULL;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+
+ pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+ /* take decodebin/sinkbin */
+ if (name[0] == 'v') {
+ wfd_sink_debug("=========== >>>>>>>>>> Received VIDEO pad...");
+
+ MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL, NULL);
+
+ gst_pad_add_probe(pad,
+ GST_PAD_PROBE_TYPE_BUFFER,
+ _mm_wfd_sink_check_running_time,
+ (gpointer)wfd_sink,
+ NULL);
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink)) {
+ wfd_sink_error("failed to prepare video pipeline....");
+ goto ERROR;
+ }
+
+ if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst)
+ decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+ if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst)
+ sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+ } else if (name[0] == 'a') {
+ wfd_sink_debug("=========== >>>>>>>>>> Received AUDIO pad...");
+
+ MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL, NULL);
+
+ gst_pad_add_probe(pad,
+ GST_PAD_PROBE_TYPE_BUFFER,
+ _mm_wfd_sink_check_running_time,
+ (gpointer)wfd_sink,
+ NULL);
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink)) {
+ wfd_sink_error("failed to prepare audio pipeline....");
+ goto ERROR;
+ }
+
+ if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst)
+ decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+ if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst)
+ sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+ } else {
+ wfd_sink_error("unexceptable pad is added!!!");
+ return;
+ }
+
+ srcpad = gst_object_ref(pad);
+
+ /* add decodebin and link */
+ if (decodebin) {
+ if (!gst_bin_add(GST_BIN(pipeline), decodebin)) {
+ wfd_sink_error("failed to add %s to pipeline",
+ GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+ goto ERROR;
+ }
+
+ sinkpad = gst_element_get_static_pad(decodebin, "sink");
+ if (!sinkpad) {
+ wfd_sink_error("failed to get sink pad from %s",
+ GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+ goto ERROR;
+ }
+
+ if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
+ wfd_sink_error("failed to link %s and %s",
+ GST_STR_NULL(GST_PAD_NAME(srcpad)),
+ GST_STR_NULL(GST_PAD_NAME(sinkpad)));
+ goto ERROR;
+ }
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+
+ srcpad = gst_element_get_static_pad(decodebin, "src");
+ if (!srcpad) {
+ wfd_sink_error("failed to get src pad from %s",
+ GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+ goto ERROR;
+ }
+ } else {
+ wfd_sink_warning("going on without decodebin...");
+ }
+
+ /* add sinkbin and link */
+ if (sinkbin) {
+ if (!gst_bin_add(GST_BIN(pipeline), sinkbin)) {
+ wfd_sink_error("failed to add %s to pipeline",
+ GST_STR_NULL(GST_ELEMENT_NAME(sinkbin)));
+ goto ERROR;
+ }
+
+ sinkpad = gst_element_get_static_pad(sinkbin, "sink");
+ if (!sinkpad) {
+ wfd_sink_error("failed to get sink pad from %s",
+ GST_STR_NULL(GST_ELEMENT_NAME(sinkbin)));
+ goto ERROR;
+ }
+
+ if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
+ wfd_sink_error("failed to link %s and %s",
+ GST_STR_NULL(GST_PAD_NAME(srcpad)),
+ GST_STR_NULL(GST_PAD_NAME(sinkpad)));
+ goto ERROR;
+ }
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+ } else {
+ wfd_sink_error("there is no sinkbin...");
+ goto ERROR;
+ }
+
+
+ /* run */
+ if (decodebin) {
+ if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(decodebin))) {
+ wfd_sink_error("failed to sync %s state with parent",
+ GST_STR_NULL(GST_PAD_NAME(decodebin)));
+ goto ERROR;
+ }
+ }
+
+ if (sinkbin) {
+ if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(sinkbin))) {
+ wfd_sink_error("failed to sync %s state with parent",
+ GST_STR_NULL(GST_PAD_NAME(sinkbin)));
+ goto ERROR;
+ }
+ }
+
+ if (name[0] == 'v') {
+ MMWFDSINK_GENERATE_DOT_IF_ENABLED(wfd_sink, "video-pad-added-pipeline");
+ } else if (name[0] == 'a') {
+ MMWFDSINK_GENERATE_DOT_IF_ENABLED(wfd_sink, "audio-pad-added-pipeline");
+ }
+
+ MMWFDSINK_FREEIF(name);
+
+ wfd_sink_debug_fleave();
+
+ return;
+
+ /* ERRORS */
+ERROR:
+ MMWFDSINK_FREEIF(name);
+
+ if (srcpad)
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+
+ if (sinkpad)
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+
+ /* need to notify to app */
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+
+ return;
+}
+
+static void
+__mm_wfd_sink_change_av_format(GstElement *wfdsrc, gpointer *need_to_flush, gpointer data)
+{
+ mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_if_fail(wfd_sink);
+ wfd_sink_return_if_fail(need_to_flush);
+
+ if (MMWFDSINK_CURRENT_STATE(wfd_sink) == MM_WFD_SINK_STATE_PLAYING) {
+ wfd_sink_debug("need to flush pipeline");
+ *need_to_flush = (gpointer) TRUE;
+ } else {
+ wfd_sink_debug("don't need to flush pipeline");
+ *need_to_flush = (gpointer) FALSE;
+ }
+
+
+ wfd_sink_debug_fleave();
+}
+
+
+static void
+__mm_wfd_sink_update_stream_info(GstElement *wfdsrc, GstStructure *str, gpointer data)
+{
+ mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
+ MMWFDSinkStreamInfo *stream_info = NULL;
+ gint is_valid_audio_format = FALSE;
+ gint is_valid_video_format = FALSE;
+ gint audio_codec = MM_WFD_SINK_AUDIO_CODEC_NONE;
+ gint video_codec = MM_WFD_SINK_VIDEO_CODEC_NONE;
+ gchar *audio_format;
+ gchar *video_format;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_if_fail(str && GST_IS_STRUCTURE(str));
+ wfd_sink_return_if_fail(wfd_sink);
+
+ stream_info = &wfd_sink->stream_info;
+
+ audio_codec = wfd_sink->stream_info.audio_stream_info.codec;
+ video_codec = wfd_sink->stream_info.video_stream_info.codec;
+
+ if (gst_structure_has_field(str, "audio_format")) {
+ is_valid_audio_format = TRUE;
+ audio_format = g_strdup(gst_structure_get_string(str, "audio_format"));
+ if (g_strrstr(audio_format, "AAC"))
+ stream_info->audio_stream_info.codec = MM_WFD_SINK_AUDIO_CODEC_AAC;
+ else if (g_strrstr(audio_format, "AC3"))
+ stream_info->audio_stream_info.codec = MM_WFD_SINK_AUDIO_CODEC_AC3;
+ else if (g_strrstr(audio_format, "LPCM"))
+ stream_info->audio_stream_info.codec = MM_WFD_SINK_AUDIO_CODEC_LPCM;
+ else {
+ wfd_sink_error("invalid audio format(%s)...", audio_format);
+ is_valid_audio_format = FALSE;
+ }
+
+ if (is_valid_audio_format == TRUE) {
+ if (gst_structure_has_field(str, "audio_rate"))
+ gst_structure_get_int(str, "audio_rate", &stream_info->audio_stream_info.sample_rate);
+ if (gst_structure_has_field(str, "audio_channels"))
+ gst_structure_get_int(str, "audio_channels", &stream_info->audio_stream_info.channels);
+ if (gst_structure_has_field(str, "audio_bitwidth"))
+ gst_structure_get_int(str, "audio_bitwidth", &stream_info->audio_stream_info.bitwidth);
+
+ if (audio_codec != MM_WFD_SINK_AUDIO_CODEC_NONE) {
+ if (audio_codec != stream_info->audio_stream_info.codec) {
+ wfd_sink_debug("audio codec is changed...need to change audio decodebin");
+ }
+ } else {
+ WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_PREPARE_A_PIPELINE);
+ }
+
+ wfd_sink_debug("audio_format : %s \n \t rate : %d \n \t channels : %d \n \t bitwidth : %d \n \t",
+ audio_format,
+ stream_info->audio_stream_info.sample_rate,
+ stream_info->audio_stream_info.channels,
+ stream_info->audio_stream_info.bitwidth);
+ }
+ }
+
+ if (gst_structure_has_field(str, "video_format")) {
+ is_valid_video_format = TRUE;
+ video_format = g_strdup(gst_structure_get_string(str, "video_format"));
+ if (!g_strrstr(video_format, "H264")) {
+ wfd_sink_error("invalid video format(%s)...", video_format);
+ is_valid_video_format = FALSE;
+ }
+
+ if (is_valid_video_format == TRUE) {
+ stream_info->video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_H264;
+
+ if (gst_structure_has_field(str, "video_width"))
+ gst_structure_get_int(str, "video_width", &stream_info->video_stream_info.width);
+ if (gst_structure_has_field(str, "video_height"))
+ gst_structure_get_int(str, "video_height", &stream_info->video_stream_info.height);
+ if (gst_structure_has_field(str, "video_framerate"))
+ gst_structure_get_int(str, "video_framerate", &stream_info->video_stream_info.frame_rate);
+
+ if (video_codec != MM_WFD_SINK_AUDIO_CODEC_NONE) {
+ if (video_codec != stream_info->video_stream_info.codec) {
+ wfd_sink_debug("video codec is changed...need to change video decodebin");
+ }
+ } else {
+ WFD_SINK_MANAGER_APPEND_CMD(wfd_sink, WFD_SINK_MANAGER_CMD_PREPARE_V_PIPELINE);
+ }
+
+ wfd_sink_debug("video_format : %s \n \t width : %d \n \t height : %d \n \t frame_rate : %d \n \t",
+ video_format,
+ stream_info->video_stream_info.width,
+ stream_info->video_stream_info.height,
+ stream_info->video_stream_info.frame_rate);
+ }
+ }
+
+ WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
+
+ wfd_sink_debug_fleave();
+}
+
+static int __mm_wfd_sink_prepare_source(mm_wfd_sink_t *wfd_sink, GstElement *wfdsrc)
+{
+ GstStructure *audio_param = NULL;
+ GstStructure *video_param = NULL;
+ GstStructure *hdcp_param = NULL;
+ gint hdcp_version = 0;
+ gint hdcp_port = 0;
+ guint CEA_resolution = 0;
+ guint VESA_resolution = 0;
+ guint HH_resolution = 0;
+ GObjectClass *klass;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(wfdsrc, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ klass = G_OBJECT_GET_CLASS(G_OBJECT(wfdsrc));
+
+ g_object_set(G_OBJECT(wfdsrc), "debug", wfd_sink->ini.set_debug_property, NULL);
+ g_object_set(G_OBJECT(wfdsrc), "enable-pad-probe", wfd_sink->ini.enable_wfdsrc_pad_probe, NULL);
+ if (g_object_class_find_property(klass, "udp-buffer-size"))
+ g_object_set(G_OBJECT(wfdsrc), "udp-buffer-size", 2097152, NULL);
+ if (g_object_class_find_property(klass, "do-request"))
+ g_object_set(G_OBJECT(wfdsrc), "do-request", wfd_sink->ini.enable_retransmission, NULL);
+ if (g_object_class_find_property(klass, "latency"))
+ g_object_set(G_OBJECT(wfdsrc), "latency", wfd_sink->ini.jitter_buffer_latency, NULL);
+
+ audio_param = gst_structure_new("audio_param",
+ "audio_codec", G_TYPE_UINT, wfd_sink->ini.audio_codec,
+ "audio_latency", G_TYPE_UINT, wfd_sink->ini.audio_latency,
+ "audio_channels", G_TYPE_UINT, wfd_sink->ini.audio_channel,
+ "audio_sampling_frequency", G_TYPE_UINT, wfd_sink->ini.audio_sampling_frequency,
+ NULL);
+
+ CEA_resolution = wfd_sink->ini.video_cea_support;
+ VESA_resolution = wfd_sink->ini.video_vesa_support;
+ HH_resolution = wfd_sink->ini.video_hh_support;
+
+ __mm_wfd_sink_prepare_video_resolution(wfd_sink->supportive_resolution, &CEA_resolution, &VESA_resolution, &HH_resolution);
+
+ wfd_sink_debug("set video resolution CEA[%x] VESA[%x] HH[%x]", CEA_resolution, VESA_resolution, HH_resolution);
+
+ video_param = gst_structure_new("video_param",
+ "video_codec", G_TYPE_UINT, wfd_sink->ini.video_codec,
+ "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.video_native_resolution,
+ "video_cea_support", G_TYPE_UINT, CEA_resolution,
+ "video_vesa_support", G_TYPE_UINT, VESA_resolution,
+ "video_hh_support", G_TYPE_UINT, HH_resolution,
+ "video_profile", G_TYPE_UINT, wfd_sink->ini.video_profile,
+ "video_level", G_TYPE_UINT, wfd_sink->ini.video_level,
+ "video_latency", G_TYPE_UINT, wfd_sink->ini.video_latency,
+ "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.video_vertical_resolution,
+ "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.video_horizontal_resolution,
+ "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.video_minimum_slicing,
+ "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.video_slice_enc_param,
+ "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.video_framerate_control_support,
+ NULL);
+
+ mm_attrs_get_int_by_name(wfd_sink->attrs, "hdcp_version", &hdcp_version);
+ mm_attrs_get_int_by_name(wfd_sink->attrs, "hdcp_port", &hdcp_port);
+ wfd_sink_debug("set hdcp version %d with %d port", hdcp_version, hdcp_port);
+
+ hdcp_param = gst_structure_new("hdcp_param",
+ "hdcp_version", G_TYPE_INT, hdcp_version,
+ "hdcp_port_no", G_TYPE_INT, hdcp_port,
+ NULL);
+
+ g_object_set(G_OBJECT(wfdsrc), "audio-param", audio_param, NULL);
+ g_object_set(G_OBJECT(wfdsrc), "video-param", video_param, NULL);
+ g_object_set(G_OBJECT(wfdsrc), "hdcp-param", hdcp_param, NULL);
+
+ g_signal_connect(wfdsrc, "update-media-info", G_CALLBACK(__mm_wfd_sink_update_stream_info), wfd_sink);
+
+ g_signal_connect(wfdsrc, "change-av-format", G_CALLBACK(__mm_wfd_sink_change_av_format), wfd_sink);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_prepare_demux(mm_wfd_sink_t *wfd_sink, GstElement *demux)
+{
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(demux, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ g_signal_connect(demux, "pad-added", G_CALLBACK(__mm_wfd_sink_demux_pad_added), wfd_sink);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static void __mm_wfd_sink_queue_overrun(GstElement *element, gpointer u_data)
+{
+ wfd_sink_debug_fenter();
+
+ return_if_fail(element);
+
+ wfd_sink_warning("%s is overrun",
+ GST_STR_NULL(GST_ELEMENT_NAME(element)));
+
+ wfd_sink_debug_fleave();
+
+ return;
+}
+
+static void __mm_wfd_sink_prepare_queue(mm_wfd_sink_t *wfd_sink, GstElement *queue)
+{
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_if_fail(wfd_sink);
+ wfd_sink_return_if_fail(queue);
+
+ /* set maximum buffer size of queue as 3sec */
+ g_object_set(G_OBJECT(queue), "max-size-bytes", 0, NULL);
+ g_object_set(G_OBJECT(queue), "max-size-buffers", 0, NULL);
+ g_object_set(G_OBJECT(queue), "max-size-time", (guint64)3000000000ULL, NULL);
+ g_signal_connect(queue, "overrun", G_CALLBACK(__mm_wfd_sink_queue_overrun), wfd_sink);
+
+ wfd_sink_debug_fleave();
+
+ return;
+}
+
+
+static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+ MMWFDSinkGstElement *mainbin = NULL;
+ GList *element_bucket = NULL;
+ GstBus *bus = NULL;
+ int i;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink_return_val_if_fail(wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* Create pipeline */
+ wfd_sink->pipeline = (MMWFDSinkGstPipelineInfo *) g_malloc0(sizeof(MMWFDSinkGstPipelineInfo));
+ if (wfd_sink->pipeline == NULL)
+ goto CREATE_ERROR;
+
+ memset(wfd_sink->pipeline, 0, sizeof(MMWFDSinkGstPipelineInfo));
+
+ /* create mainbin */
+ mainbin = (MMWFDSinkGstElement *) g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_M_NUM);
+ if (mainbin == NULL)
+ goto CREATE_ERROR;
+
+ memset(mainbin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_M_NUM);
+
+ /* create pipeline */
+ mainbin[WFD_SINK_M_PIPE].id = WFD_SINK_M_PIPE;
+ mainbin[WFD_SINK_M_PIPE].gst = gst_pipeline_new("wfdsink");
+ if (!mainbin[WFD_SINK_M_PIPE].gst) {
+ wfd_sink_error("failed to create pipeline");
+ goto CREATE_ERROR;
+ }
+
+ /* create wfdsrc */
+ MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_SRC, wfd_sink->ini.name_of_source, "wfdsink_source", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_SRC].gst, "src");
+ if (mainbin[WFD_SINK_M_SRC].gst) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_source(wfd_sink, mainbin[WFD_SINK_M_SRC].gst)) {
+ wfd_sink_error("failed to prepare wfdsrc...");
+ goto CREATE_ERROR;
+ }
+ }
+
+ /* create rtpmp2tdepay */
+ MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_DEPAY, "rtpmp2tdepay", "wfdsink_depay", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_DEPAY].gst, "src");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_DEPAY].gst, "sink");
+
+ MMWFDSINK_TS_DATA_DUMP(wfd_sink, mainbin[WFD_SINK_M_DEPAY].gst, "src");
+
+ /* create tsdemuxer*/
+ MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_DEMUX, wfd_sink->ini.name_of_tsdemux, "wfdsink_demux", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_DEMUX].gst, "sink");
+ if (mainbin[WFD_SINK_M_DEMUX].gst) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_demux(wfd_sink, mainbin[WFD_SINK_M_DEMUX].gst)) {
+ wfd_sink_error("failed to prepare demux...");
+ goto CREATE_ERROR;
+ }
+ }
+
+ /* adding created elements to pipeline */
+ if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(mainbin[WFD_SINK_M_PIPE].gst), element_bucket, FALSE)) {
+ wfd_sink_error("failed to add elements");
+ goto CREATE_ERROR;
+ }
+
+ /* linking elements in the bucket by added order. */
+ if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
+ wfd_sink_error("failed to link elements");
+ goto CREATE_ERROR;
+ }
+
+ /* connect bus callback */
+ bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[WFD_SINK_M_PIPE].gst));
+ if (!bus) {
+ wfd_sink_error("cannot get bus from pipeline.");
+ goto CREATE_ERROR;
+ }
+
+ /* add bus message callback*/
+ gst_bus_add_watch(bus, (GstBusFunc)_mm_wfd_sink_msg_callback, wfd_sink);
+
+ /* set sync handler to get tag synchronously */
+ gst_bus_set_sync_handler(bus, _mm_wfd_bus_sync_callback, wfd_sink, NULL);
+
+ g_list_free(element_bucket);
+ gst_object_unref(GST_OBJECT(bus));
+
+ /* now we have completed mainbin. take it */
+ wfd_sink->pipeline->mainbin = mainbin;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+ /* ERRORS */
+CREATE_ERROR:
+ wfd_sink_error("ERROR : releasing pipeline");
+
+ if (element_bucket)
+ g_list_free(element_bucket);
+ element_bucket = NULL;
+
+ /* finished */
+ if (bus)
+ gst_object_unref(GST_OBJECT(bus));
+ bus = NULL;
+
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_M_NUM; i++) { /* NOTE : skip pipeline */
+ if (mainbin != NULL && mainbin[i].gst) {
+ GstObject *parent = NULL;
+ parent = gst_element_get_parent(mainbin[i].gst);
+
+ if (!parent) {
+ gst_object_unref(GST_OBJECT(mainbin[i].gst));
+ mainbin[i].gst = NULL;
+ } else {
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+
+ /* release mainbin with it's childs */
+ if (mainbin != NULL && mainbin[WFD_SINK_M_PIPE].gst)
+ gst_object_unref(GST_OBJECT(mainbin[WFD_SINK_M_PIPE].gst));
+
+ MMWFDSINK_FREEIF(mainbin);
+
+ MMWFDSINK_FREEIF(wfd_sink->pipeline);
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink)
+{
+ MMWFDSinkGstElement *a_decodebin = NULL;
+ MMWFDSinkGstElement *first_element = NULL;
+ MMWFDSinkGstElement *last_element = NULL;
+ GList *element_bucket = NULL;
+ GstPad *sinkpad = NULL;
+ GstPad *srcpad = NULL;
+ GstPad *ghostpad = NULL;
+ GList *first_list = NULL;
+ GList *last_list = NULL;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->a_decodebin &&
+ wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->audio_decodebin_is_linked) {
+ wfd_sink_debug("audio decodebin is already linked... nothing to do");
+ return MM_ERROR_NONE;
+ }
+
+ /* take audio decodebin */
+ a_decodebin = wfd_sink->pipeline->a_decodebin;
+
+ /* check audio queue */
+ if (a_decodebin[WFD_SINK_A_D_QUEUE].gst)
+ element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_QUEUE]);
+
+ /* check audio hdcp */
+ if (a_decodebin[WFD_SINK_A_D_HDCP].gst)
+ element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_HDCP]);
+
+ /* check audio codec */
+ switch (wfd_sink->stream_info.audio_stream_info.codec) {
+ case MM_WFD_SINK_AUDIO_CODEC_LPCM:
+ if (a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst)
+ element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER]);
+ if (a_decodebin[WFD_SINK_A_D_LPCM_FILTER].gst) {
+ GstCaps *caps = NULL;
+ element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_LPCM_FILTER]);
+ caps = gst_caps_new_simple("audio/x-raw",
+ "rate", G_TYPE_INT, wfd_sink->stream_info.audio_stream_info.sample_rate,
+ "channels", G_TYPE_INT, wfd_sink->stream_info.audio_stream_info.channels,
+ "format", G_TYPE_STRING, "S16BE", NULL);
+
+ g_object_set(G_OBJECT(a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst), "caps", caps, NULL);
+ gst_object_unref(GST_OBJECT(caps));
+ }
+ break;
+
+ case MM_WFD_SINK_AUDIO_CODEC_AAC:
+ if (a_decodebin[WFD_SINK_A_D_AAC_PARSE].gst)
+ element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AAC_PARSE]);
+ if (a_decodebin[WFD_SINK_A_D_AAC_DEC].gst)
+ element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AAC_DEC]);
+ break;
+
+ case MM_WFD_SINK_AUDIO_CODEC_AC3:
+ if (a_decodebin[WFD_SINK_A_D_AC3_PARSE].gst)
+ element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AC3_PARSE]);
+ if (a_decodebin[WFD_SINK_A_D_AC3_DEC].gst)
+ element_bucket = g_list_append(element_bucket, &a_decodebin[WFD_SINK_A_D_AC3_DEC]);
+ break;
+
+ default:
+ wfd_sink_error("audio codec is not decied yet. cannot link audio decodebin...");
+ return MM_ERROR_WFD_INTERNAL;
+ break;
+ }
+
+ if (element_bucket == NULL) {
+ wfd_sink_error("there are no elements to be linked in the audio decodebin, destroy it");
+ if (MM_ERROR_NONE != __mm_wfd_sink_destroy_audio_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to destroy audio decodebin");
+ goto fail_to_link;
+ }
+ goto done;
+ }
+
+ /* adding elements to audio decodebin */
+ if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(a_decodebin[WFD_SINK_A_D_BIN].gst), element_bucket, FALSE)) {
+ wfd_sink_error("failed to add elements to audio decodebin");
+ goto fail_to_link;
+ }
+
+ /* linking elements in the bucket by added order. */
+ if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
+ wfd_sink_error("failed to link elements of the audio decodebin");
+ goto fail_to_link;
+ }
+
+ /* get first element's sinkpad for creating ghostpad */
+ first_list = g_list_first(element_bucket);
+ if (first_list == NULL) {
+ wfd_sink_error("failed to get first list of the element_bucket");
+ goto fail_to_link;
+ }
+
+ first_element = (MMWFDSinkGstElement *)first_list->data;
+ if (!first_element) {
+ wfd_sink_error("failed to get first element of the audio decodebin");
+ goto fail_to_link;
+ }
+
+ sinkpad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
+ if (!sinkpad) {
+ wfd_sink_error("failed to get sink pad from element(%s)",
+ GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
+ goto fail_to_link;
+ }
+
+ ghostpad = gst_ghost_pad_new("sink", sinkpad);
+ if (!ghostpad) {
+ wfd_sink_error("failed to create ghostpad of audio decodebin");
+ goto fail_to_link;
+ }
+
+ if (FALSE == gst_element_add_pad(a_decodebin[WFD_SINK_A_D_BIN].gst, ghostpad)) {
+ wfd_sink_error("failed to add ghostpad to audio decodebin");
+ goto fail_to_link;
+ }
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+
+
+ /* get last element's src for creating ghostpad */
+ last_list = g_list_last(element_bucket);
+ if (last_list == NULL) {
+ wfd_sink_error("failed to get last list of the element_bucket");
+ goto fail_to_link;
+ }
+
+ last_element = (MMWFDSinkGstElement *)last_list->data;
+ if (!last_element) {
+ wfd_sink_error("failed to get last element of the audio decodebin");
+ goto fail_to_link;
+ }
+
+ srcpad = gst_element_get_static_pad(GST_ELEMENT(last_element->gst), "src");
+ if (!srcpad) {
+ wfd_sink_error("failed to get src pad from element(%s)",
+ GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
+ goto fail_to_link;
+ }
+
+ ghostpad = gst_ghost_pad_new("src", srcpad);
+ if (!ghostpad) {
+ wfd_sink_error("failed to create ghostpad of audio decodebin");
+ goto fail_to_link;
+ }
+
+ if (FALSE == gst_element_add_pad(a_decodebin[WFD_SINK_A_D_BIN].gst, ghostpad)) {
+ wfd_sink_error("failed to add ghostpad to audio decodebin");
+ goto fail_to_link;
+ }
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+
+ g_list_free(element_bucket);
+
+done:
+ wfd_sink->audio_decodebin_is_linked = TRUE;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+ /* ERRORS*/
+fail_to_link:
+ if (srcpad)
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+
+ if (sinkpad)
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+
+ g_list_free(element_bucket);
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+static int __mm_wfd_sink_prepare_audiosink(mm_wfd_sink_t *wfd_sink, GstElement *audio_sink)
+{
+ wfd_sink_debug_fenter();
+
+ /* check audiosink is created */
+ wfd_sink_return_val_if_fail(audio_sink, MM_ERROR_WFD_INVALID_ARGUMENT);
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ g_object_set(G_OBJECT(audio_sink), "provide-clock", FALSE, NULL);
+ g_object_set(G_OBJECT(audio_sink), "buffer-time", 100000LL, NULL);
+ g_object_set(G_OBJECT(audio_sink), "slave-method", 2, NULL);
+ g_object_set(G_OBJECT(audio_sink), "async", wfd_sink->ini.audio_sink_async, NULL);
+ g_object_set(G_OBJECT(audio_sink), "ts-offset", (gint64)wfd_sink->ini.sink_ts_offset, NULL);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ MMWFDSinkGstElement *a_decodebin = NULL;
+ GstObject *parent = NULL;
+ int i;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->pipeline &&
+ wfd_sink->pipeline->a_decodebin &&
+ wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
+ a_decodebin = wfd_sink->pipeline->a_decodebin;
+ } else {
+ wfd_sink_debug("audio decodebin is not created, nothing to destroy");
+ return MM_ERROR_NONE;
+ }
+
+ parent = gst_element_get_parent(a_decodebin[WFD_SINK_A_D_BIN].gst);
+ if (!parent) {
+ wfd_sink_debug("audio decodebin has no parent.. need to relase by itself");
+
+ if (GST_STATE(a_decodebin[WFD_SINK_A_D_BIN].gst) >= GST_STATE_READY) {
+ wfd_sink_debug("try to change state of audio decodebin to NULL");
+ ret = gst_element_set_state(a_decodebin[WFD_SINK_A_D_BIN].gst, GST_STATE_NULL);
+ if (ret != GST_STATE_CHANGE_SUCCESS) {
+ wfd_sink_error("failed to change state of audio decodebin to NULL");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_A_D_NUM; i++) { /* NOTE : skip bin */
+ if (a_decodebin[i].gst) {
+ parent = gst_element_get_parent(a_decodebin[i].gst);
+ if (!parent) {
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
+ ((GObject *) a_decodebin[i].gst)->ref_count);
+ gst_object_unref(GST_OBJECT(a_decodebin[i].gst));
+ a_decodebin[i].gst = NULL;
+ } else {
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(a_decodebin[i].gst)),
+ ((GObject *) a_decodebin[i].gst)->ref_count);
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+
+ /* release audio decodebin with it's childs */
+ if (a_decodebin[WFD_SINK_A_D_BIN].gst)
+ gst_object_unref(GST_OBJECT(a_decodebin[WFD_SINK_A_D_BIN].gst));
+
+ } else {
+ wfd_sink_debug("audio decodebin has parent(%s), unref it ",
+ GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+
+ gst_object_unref(GST_OBJECT(parent));
+ }
+
+ wfd_sink->audio_decodebin_is_linked = FALSE;
+
+ MMWFDSINK_FREEIF(wfd_sink->pipeline->a_decodebin);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
+{
+ MMWFDSinkGstElement *a_decodebin = NULL;
+ gint audio_codec = WFD_AUDIO_UNKNOWN;
+ GList *element_bucket = NULL;
+ gboolean link = TRUE;
+ gint i = 0;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* check audio decodebin could be linked now */
+ switch (wfd_sink->stream_info.audio_stream_info.codec) {
+ case MM_WFD_SINK_AUDIO_CODEC_AAC:
+ audio_codec = WFD_AUDIO_AAC;
+ link = TRUE;
+ break;
+ case MM_WFD_SINK_AUDIO_CODEC_AC3:
+ audio_codec = WFD_AUDIO_AC3;
+ link = TRUE;
+ break;
+ case MM_WFD_SINK_AUDIO_CODEC_LPCM:
+ audio_codec = WFD_AUDIO_LPCM;
+ link = TRUE;
+ break;
+ case MM_WFD_SINK_AUDIO_CODEC_NONE:
+ default:
+ wfd_sink_debug("audio decodebin could NOT be linked now, just create");
+ audio_codec = wfd_sink->ini.audio_codec;
+ link = FALSE;
+ break;
+ }
+
+ /* alloc handles */
+ a_decodebin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_A_D_NUM);
+ if (!a_decodebin) {
+ wfd_sink_error("failed to allocate memory for audio decodebin");
+ return MM_ERROR_WFD_NO_FREE_SPACE;
+ }
+
+ memset(a_decodebin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_A_D_NUM);
+
+ /* create audio decodebin */
+ a_decodebin[WFD_SINK_A_D_BIN].id = WFD_SINK_A_D_BIN;
+ a_decodebin[WFD_SINK_A_D_BIN].gst = gst_bin_new("audio_deocebin");
+ if (!a_decodebin[WFD_SINK_A_D_BIN].gst) {
+ wfd_sink_error("failed to create audio decodebin");
+ goto CREATE_ERROR;
+ }
+
+ /* create queue */
+ MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_QUEUE, "queue", "audio_queue", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_QUEUE].gst, "sink");
+ if (a_decodebin[WFD_SINK_A_D_QUEUE].gst)
+ __mm_wfd_sink_prepare_queue(wfd_sink, a_decodebin[WFD_SINK_A_D_QUEUE].gst);
+
+ /* create hdcp */
+ MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_HDCP, wfd_sink->ini.name_of_audio_hdcp, "audio_hdcp", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_HDCP].gst, "sink");
+
+ /* create codec */
+ audio_codec = wfd_sink->ini.audio_codec;
+ if (audio_codec & WFD_AUDIO_LPCM) {
+ /* create LPCM converter */
+ MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_LPCM_CONVERTER, wfd_sink->ini.name_of_lpcm_converter, "audio_lpcm_convert", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_LPCM_CONVERTER].gst, "src");
+
+ /* create LPCM filter */
+ MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_LPCM_FILTER, wfd_sink->ini.name_of_lpcm_filter, "audio_lpcm_filter", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_LPCM_FILTER].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_LPCM_FILTER].gst, "src");
+ }
+
+ if (audio_codec & WFD_AUDIO_AAC) {
+ /* create AAC parse */
+ MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_AAC_PARSE, wfd_sink->ini.name_of_aac_parser, "audio_aac_parser", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AAC_PARSE].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AAC_PARSE].gst, "src");
+
+ /* create AAC decoder */
+ MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_AAC_DEC, wfd_sink->ini.name_of_aac_decoder, "audio_aac_dec", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AAC_DEC].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AAC_DEC].gst, "src");
+ }
+
+ if (audio_codec & WFD_AUDIO_AC3) {
+ /* create AC3 parser */
+ MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_AC3_PARSE, wfd_sink->ini.name_of_ac3_parser, "audio_ac3_parser", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AC3_PARSE].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AC3_PARSE].gst, "src");
+
+ /* create AC3 decoder */
+ MMWFDSINK_CREATE_ELEMENT(a_decodebin, WFD_SINK_A_D_AC3_DEC, wfd_sink->ini.name_of_ac3_decoder, "audio_ac3_dec", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AC3_DEC].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_AC3_DEC].gst, "src");
+ }
+
+ g_list_free(element_bucket);
+
+ /* take it */
+ wfd_sink->pipeline->a_decodebin = a_decodebin;
+
+ /* link audio decodebin if audio codec is fixed */
+ if (link) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_link_audio_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to link audio decodebin, destroy audio decodebin");
+ __mm_wfd_sink_destroy_audio_decodebin(wfd_sink);
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+CREATE_ERROR:
+ wfd_sink_error("failed to create audio decodebin, release all");
+
+ g_list_free(element_bucket);
+
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_A_D_NUM; i++) { /* NOTE : skip bin */
+ if (a_decodebin != NULL && a_decodebin[i].gst) {
+ GstObject *parent = NULL;
+ parent = gst_element_get_parent(a_decodebin[i].gst);
+
+ if (!parent) {
+ gst_object_unref(GST_OBJECT(a_decodebin[i].gst));
+ a_decodebin[i].gst = NULL;
+ } else {
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+
+ /* release audioo decodebin with it's childs */
+ if (a_decodebin != NULL && a_decodebin[WFD_SINK_A_D_BIN].gst)
+ gst_object_unref(GST_OBJECT(a_decodebin[WFD_SINK_A_D_BIN].gst));
+
+ MMWFDSINK_FREEIF(a_decodebin);
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+static int __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ MMWFDSinkGstElement *a_sinkbin = NULL;
+ GstObject *parent = NULL;
+ int i;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->pipeline &&
+ wfd_sink->pipeline->a_sinkbin &&
+ wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+ a_sinkbin = wfd_sink->pipeline->a_sinkbin;
+ } else {
+ wfd_sink_debug("audio sinkbin is not created, nothing to destroy");
+ return MM_ERROR_NONE;
+ }
+
+ parent = gst_element_get_parent(a_sinkbin[WFD_SINK_A_S_BIN].gst);
+ if (!parent) {
+ wfd_sink_debug("audio decodebin has no parent.. need to relase by itself");
+
+ if (GST_STATE(a_sinkbin[WFD_SINK_A_S_BIN].gst) >= GST_STATE_READY) {
+ wfd_sink_debug("try to change state of audio decodebin to NULL");
+ ret = gst_element_set_state(a_sinkbin[WFD_SINK_A_S_BIN].gst, GST_STATE_NULL);
+ if (ret != GST_STATE_CHANGE_SUCCESS) {
+ wfd_sink_error("failed to change state of audio decodebin to NULL");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_A_S_NUM; i++) { /* NOTE : skip bin */
+ if (a_sinkbin[i].gst) {
+ parent = gst_element_get_parent(a_sinkbin[i].gst);
+ if (!parent) {
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
+ ((GObject *) a_sinkbin[i].gst)->ref_count);
+ gst_object_unref(GST_OBJECT(a_sinkbin[i].gst));
+ a_sinkbin[i].gst = NULL;
+ } else {
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(a_sinkbin[i].gst)),
+ ((GObject *) a_sinkbin[i].gst)->ref_count);
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+
+ /* release audio decodebin with it's childs */
+ if (a_sinkbin[WFD_SINK_A_S_BIN].gst)
+ gst_object_unref(GST_OBJECT(a_sinkbin[WFD_SINK_A_S_BIN].gst));
+
+ } else {
+ wfd_sink_debug("audio sinkbin has parent(%s), unref it ",
+ GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+
+ gst_object_unref(GST_OBJECT(parent));
+ }
+
+ MMWFDSINK_FREEIF(wfd_sink->pipeline->a_sinkbin);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
+{
+ MMWFDSinkGstElement *a_sinkbin = NULL;
+ MMWFDSinkGstElement *first_element = NULL;
+ GList *element_bucket = NULL;
+ GstPad *ghostpad = NULL;
+ GstPad *pad = NULL;
+ gint i = 0;
+ GList *first_list = NULL;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* alloc handles */
+ a_sinkbin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_A_S_NUM);
+ if (!a_sinkbin) {
+ wfd_sink_error("failed to allocate memory for audio sinkbin");
+ return MM_ERROR_WFD_NO_FREE_SPACE;
+ }
+
+ memset(a_sinkbin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_A_S_NUM);
+
+ /* create audio sinkbin */
+ a_sinkbin[WFD_SINK_A_S_BIN].id = WFD_SINK_A_S_BIN;
+ a_sinkbin[WFD_SINK_A_S_BIN].gst = gst_bin_new("audio_sinkbin");
+ if (!a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+ wfd_sink_error("failed to create audio sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ /* create resampler */
+ MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_RESAMPLER, wfd_sink->ini.name_of_audio_resampler, "audio_resampler", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_RESAMPLER].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_RESAMPLER].gst, "src");
+
+ /* create volume */
+ MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_VOLUME, wfd_sink->ini.name_of_audio_volume, "audio_volume", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_VOLUME].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_VOLUME].gst, "src");
+
+ /* create sink */
+ MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_SINK, wfd_sink->ini.name_of_audio_sink, "audio_sink", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_SINK].gst, "sink");
+ if (a_sinkbin[WFD_SINK_A_S_SINK].gst) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audiosink(wfd_sink, a_sinkbin[WFD_SINK_A_S_SINK].gst)) {
+ wfd_sink_error("failed to set audio sink property....");
+ goto CREATE_ERROR;
+ }
+ }
+
+ /* adding created elements to audio sinkbin */
+ if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(a_sinkbin[WFD_SINK_A_S_BIN].gst), element_bucket, FALSE)) {
+ wfd_sink_error("failed to add elements to audio sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ /* linking elements in the bucket by added order. */
+ if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
+ wfd_sink_error("failed to link elements fo the audio sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ /* get first element's of the audio sinkbin */
+ first_list = g_list_first(element_bucket);
+ if (first_list == NULL) {
+ wfd_sink_error("failed to get first list of the element_bucket");
+ goto CREATE_ERROR;
+ }
+
+ first_element = (MMWFDSinkGstElement *)first_list->data;
+ if (!first_element) {
+ wfd_sink_error("failed to get first element of the audio sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ /* get first element's sinkpad for creating ghostpad */
+ pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
+ if (!pad) {
+ wfd_sink_error("failed to get sink pad from element(%s)",
+ GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
+ goto CREATE_ERROR;
+ }
+
+ ghostpad = gst_ghost_pad_new("sink", pad);
+ if (!ghostpad) {
+ wfd_sink_error("failed to create ghostpad of audio sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ if (FALSE == gst_element_add_pad(a_sinkbin[WFD_SINK_A_S_BIN].gst, ghostpad)) {
+ wfd_sink_error("failed to add ghostpad to audio sinkbin");
+ goto CREATE_ERROR;
+ }
+ gst_object_unref(GST_OBJECT(pad));
+
+ g_list_free(element_bucket);
+
+ /* take it */
+ wfd_sink->pipeline->a_sinkbin = a_sinkbin;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+CREATE_ERROR:
+ wfd_sink_error("failed to create audio sinkbin, releasing all");
+
+ if (pad)
+ gst_object_unref(GST_OBJECT(pad));
+ pad = NULL;
+
+ if (ghostpad)
+ gst_object_unref(GST_OBJECT(ghostpad));
+ ghostpad = NULL;
+
+ if (element_bucket)
+ g_list_free(element_bucket);
+ element_bucket = NULL;
+
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_A_S_NUM; i++) { /* NOTE : skip bin */
+ if (a_sinkbin != NULL && a_sinkbin[i].gst) {
+ GstObject *parent = NULL;
+ parent = gst_element_get_parent(a_sinkbin[i].gst);
+
+ if (!parent) {
+ gst_object_unref(GST_OBJECT(a_sinkbin[i].gst));
+ a_sinkbin[i].gst = NULL;
+ } else {
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+
+ /* release audio sinkbin with it's childs */
+ if (a_sinkbin != NULL && a_sinkbin[WFD_SINK_A_S_BIN].gst)
+ gst_object_unref(GST_OBJECT(a_sinkbin[WFD_SINK_A_S_BIN].gst));
+
+ MMWFDSINK_FREEIF(a_sinkbin);
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_link_video_decodebin(mm_wfd_sink_t *wfd_sink)
+{
+ MMWFDSinkGstElement *v_decodebin = NULL;
+ MMWFDSinkGstElement *first_element = NULL;
+ MMWFDSinkGstElement *last_element = NULL;
+ GList *element_bucket = NULL;
+ GstPad *sinkpad = NULL;
+ GstPad *srcpad = NULL;
+ GstPad *ghostpad = NULL;
+ GList *first_list = NULL;
+ GList *last_list = NULL;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->v_decodebin &&
+ wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->video_decodebin_is_linked) {
+ wfd_sink_debug("video decodebin is already linked... nothing to do");
+ return MM_ERROR_NONE;
+ }
+
+ /* take video decodebin */
+ v_decodebin = wfd_sink->pipeline->v_decodebin;
+
+ /* check video queue */
+ if (v_decodebin[WFD_SINK_V_D_QUEUE].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_QUEUE]);
+
+ /* check video hdcp */
+ if (v_decodebin[WFD_SINK_V_D_HDCP].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_HDCP]);
+
+ /* check video codec */
+ switch (wfd_sink->stream_info.video_stream_info.codec) {
+ case MM_WFD_SINK_VIDEO_CODEC_H264:
+ if (v_decodebin[WFD_SINK_V_D_PARSE].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_PARSE]);
+ if (v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst) {
+ GstCaps *caps = NULL;
+
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_CAPSSETTER]);
+ caps = gst_caps_new_simple("video/x-h264",
+ "width", G_TYPE_INT, wfd_sink->stream_info.video_stream_info.width,
+ "height", G_TYPE_INT, wfd_sink->stream_info.video_stream_info.height,
+ "framerate", GST_TYPE_FRACTION, wfd_sink->stream_info.video_stream_info.frame_rate, 1, NULL);
+ g_object_set(G_OBJECT(v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst), "caps", caps, NULL);
+ gst_object_unref(GST_OBJECT(caps));
+ }
+ if (v_decodebin[WFD_SINK_V_D_DEC].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_DEC]);
+ break;
+
+ default:
+ wfd_sink_error("video codec is not decied yet. cannot link video decpdebin...");
+ return MM_ERROR_WFD_INTERNAL;
+ break;
+ }
+
+ if (element_bucket == NULL) {
+ wfd_sink_error("there are no elements to be linked in the video decodebin, destroy it");
+ if (MM_ERROR_NONE != __mm_wfd_sink_destroy_video_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to destroy video decodebin");
+ goto fail_to_link;
+ }
+ goto done;
+ }
+
+ /* adding elements to video decodebin */
+ if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(v_decodebin[WFD_SINK_V_D_BIN].gst), element_bucket, FALSE)) {
+ wfd_sink_error("failed to add elements to video decodebin");
+ goto fail_to_link;
+ }
+
+ /* linking elements in the bucket by added order. */
+ if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
+ wfd_sink_error("failed to link elements of the video decodebin");
+ goto fail_to_link;
+ }
+
+ /* get first element's sinkpad for creating ghostpad */
+ first_list = g_list_first(element_bucket);
+ if (first_list == NULL) {
+ wfd_sink_error("failed to get first list of the element_bucket");
+ goto fail_to_link;
+ }
+
+ first_element = (MMWFDSinkGstElement *)first_list->data;
+ if (!first_element) {
+ wfd_sink_error("failed to get first element of the video decodebin");
+ goto fail_to_link;
+ }
+
+ sinkpad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
+ if (!sinkpad) {
+ wfd_sink_error("failed to get sink pad from element(%s)",
+ GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
+ goto fail_to_link;
+ }
+
+ ghostpad = gst_ghost_pad_new("sink", sinkpad);
+ if (!ghostpad) {
+ wfd_sink_error("failed to create ghostpad of video decodebin");
+ goto fail_to_link;
+ }
+
+ if (FALSE == gst_element_add_pad(v_decodebin[WFD_SINK_V_D_BIN].gst, ghostpad)) {
+ wfd_sink_error("failed to add ghostpad to video decodebin");
+ goto fail_to_link;
+ }
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+
+
+ /* get last element's src for creating ghostpad */
+ last_list = g_list_last(element_bucket);
+ if (last_list == NULL) {
+ wfd_sink_error("failed to get last list of the element_bucket");
+ goto fail_to_link;
+ }
+
+ last_element = (MMWFDSinkGstElement *)last_list->data;
+ if (!last_element) {
+ wfd_sink_error("failed to get last element of the video decodebin");
+ goto fail_to_link;
+ }
+
+ srcpad = gst_element_get_static_pad(GST_ELEMENT(last_element->gst), "src");
+ if (!srcpad) {
+ wfd_sink_error("failed to get src pad from element(%s)",
+ GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
+ goto fail_to_link;
+ }
+
+ ghostpad = gst_ghost_pad_new("src", srcpad);
+ if (!ghostpad) {
+ wfd_sink_error("failed to create ghostpad of video decodebin");
+ goto fail_to_link;
+ }
+
+ if (FALSE == gst_element_add_pad(v_decodebin[WFD_SINK_V_D_BIN].gst, ghostpad)) {
+ wfd_sink_error("failed to add ghostpad to video decodebin");
+ goto fail_to_link;
+ }
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+
+ g_list_free(element_bucket);
+
+done:
+ wfd_sink->video_decodebin_is_linked = TRUE;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+ /* ERRORS*/
+fail_to_link:
+ if (srcpad != NULL)
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+
+ if (sinkpad != NULL)
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+
+ g_list_free(element_bucket);
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+static int __mm_wfd_sink_prepare_videodec(mm_wfd_sink_t *wfd_sink, GstElement *video_dec)
+{
+ wfd_sink_debug_fenter();
+
+ /* check video decoder is created */
+ wfd_sink_return_val_if_fail(video_dec, MM_ERROR_WFD_INVALID_ARGUMENT);
+ wfd_sink_return_val_if_fail(wfd_sink && wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_prepare_videosink(mm_wfd_sink_t *wfd_sink, GstElement *video_sink)
+{
+ gboolean visible = TRUE;
+ gint surface_type = MM_DISPLAY_SURFACE_OVERLAY;
+
+ wfd_sink_debug_fenter();
+
+ /* check videosink is created */
+ wfd_sink_return_val_if_fail(video_sink, MM_ERROR_WFD_INVALID_ARGUMENT);
+ wfd_sink_return_val_if_fail(wfd_sink && wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* update display surface */
+ mm_attrs_get_int_by_name(wfd_sink->attrs, "display_surface_type", &surface_type);
+ wfd_sink_debug("check display surface type attribute: %d", surface_type);
+ mm_attrs_get_int_by_name(wfd_sink->attrs, "display_visible", &visible);
+ wfd_sink_debug("check display visible attribute: %d", visible);
+
+ /* configuring display */
+ switch (surface_type) {
+ case MM_DISPLAY_SURFACE_EVAS: {
+ void *object = NULL;
+ gint scaling = 0;
+
+ /* common case if using evas surface */
+ mm_attrs_get_data_by_name(wfd_sink->attrs, "display_overlay", &object);
+ mm_attrs_get_int_by_name(wfd_sink->attrs, "display_evas_do_scaling", &scaling);
+ if (object) {
+ wfd_sink_debug("set video param : evas-object %x", object);
+ g_object_set(G_OBJECT(video_sink), "evas-object", object, NULL);
+ } else {
+ wfd_sink_error("no evas object");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+ break;
+
+ case MM_DISPLAY_SURFACE_OVERLAY: {
+ int wl_window_x = 0;
+ int wl_window_y = 0;
+ int wl_window_width = 0;
+ int wl_window_height = 0;
+ unsigned int wl_surface_id = 0;
+ struct wl_surface *wl_surface = NULL;
+ struct wl_display *wl_display = NULL;
+ Ecore_Wl_Window *wl_window = NULL;
+ wl_client *wlclient = NULL;
+ Evas_Object *obj = NULL;
+ void *object = NULL;
+ const char *object_type = NULL;
+ int ret = 0;
+
+ mm_attrs_get_data_by_name(wfd_sink->attrs, "display_overlay", &object);
+
+ if (object != NULL) {
+ obj = (Evas_Object *)object;
+ object_type = evas_object_type_get(obj);
+ wfd_sink_debug("window object type : %s", object_type);
+
+ /* wayland overlay surface */
+ LOGI("Wayland overlay surface type");
+ evas_object_geometry_get(obj, &wl_window_x, &wl_window_y, &wl_window_width, &wl_window_height);
+
+ wfd_sink_debug ("x[%d] y[%d] width[%d] height[%d]", wl_window_x, wl_window_y,
+ wl_window_width, wl_window_height);
+
+ wl_window = elm_win_wl_window_get(obj);
+ wl_surface = (struct wl_surface *) ecore_wl_window_surface_get(wl_window);
+
+ /* get wl_display */
+ wl_display = (struct wl_display *) ecore_wl_display_get();
+
+ ret = mm_wfd_sink_wlclient_create(&wlclient);
+ if ( ret != MM_ERROR_NONE) {
+ wfd_sink_error("Wayland client create failure");
+ return ret;
+ }
+
+ if (wl_surface && wl_display){
+ wfd_sink_debug ("surface = %p, wl_display = %p", wl_surface, wl_display);
+ wl_surface_id = mm_wfd_sink_wlclient_get_wl_window_wl_surface_id (wlclient, wl_surface, wl_display);
+ wfd_sink_debug ("wl_surface_id = %d", wl_surface_id);
+ }
+ if (wlclient) {
+ g_free(wlclient);
+ wlclient = NULL;
+ }
+
+ wfd_sink_debug("set video param : surface_id %d", wl_surface_id);
+ gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink),
+ wl_surface_id);
+ /* After setting window handle, set render rectangle */
+ gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(video_sink),
+ wl_window_x, wl_window_y, wl_window_width, wl_window_height);
+ } else {
+ wfd_sink_debug ("display object is NULL!");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+ break;
+
+ case MM_DISPLAY_SURFACE_NULL: {
+ /* do nothing */
+ wfd_sink_error("Not Supported Surface.");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ break;
+ default: {
+ wfd_sink_error("Not Supported Surface.(default case)");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ break;
+ }
+
+ g_object_set(G_OBJECT(video_sink), "qos", FALSE, NULL);
+ g_object_set(G_OBJECT(video_sink), "async", wfd_sink->ini.video_sink_async, NULL);
+ g_object_set(G_OBJECT(video_sink), "max-lateness", (gint64)wfd_sink->ini.video_sink_max_lateness, NULL);
+ g_object_set(G_OBJECT(video_sink), "visible", visible, NULL);
+ g_object_set(G_OBJECT(video_sink), "ts-offset", (gint64)(wfd_sink->ini.sink_ts_offset), NULL);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ MMWFDSinkGstElement *v_decodebin = NULL;
+ GstObject *parent = NULL;
+ int i;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->pipeline &&
+ wfd_sink->pipeline->v_decodebin &&
+ wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+ v_decodebin = wfd_sink->pipeline->v_decodebin;
+ } else {
+ wfd_sink_debug("video decodebin is not created, nothing to destroy");
+ return MM_ERROR_NONE;
+ }
+
+
+ parent = gst_element_get_parent(v_decodebin[WFD_SINK_V_D_BIN].gst);
+ if (!parent) {
+ wfd_sink_debug("video decodebin has no parent.. need to relase by itself");
+
+ if (GST_STATE(v_decodebin[WFD_SINK_V_D_BIN].gst) >= GST_STATE_READY) {
+ wfd_sink_debug("try to change state of video decodebin to NULL");
+ ret = gst_element_set_state(v_decodebin[WFD_SINK_V_D_BIN].gst, GST_STATE_NULL);
+ if (ret != GST_STATE_CHANGE_SUCCESS) {
+ wfd_sink_error("failed to change state of video decodebin to NULL");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_V_D_NUM; i++) { /* NOTE : skip bin */
+ if (v_decodebin[i].gst) {
+ parent = gst_element_get_parent(v_decodebin[i].gst);
+ if (!parent) {
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
+ ((GObject *) v_decodebin[i].gst)->ref_count);
+ gst_object_unref(GST_OBJECT(v_decodebin[i].gst));
+ v_decodebin[i].gst = NULL;
+ } else {
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[i].gst)),
+ ((GObject *) v_decodebin[i].gst)->ref_count);
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+ /* release video decodebin with it's childs */
+ if (v_decodebin[WFD_SINK_V_D_BIN].gst) {
+ gst_object_unref(GST_OBJECT(v_decodebin[WFD_SINK_V_D_BIN].gst));
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(v_decodebin[WFD_SINK_V_D_BIN].gst)),
+ ((GObject *)v_decodebin[WFD_SINK_V_D_BIN].gst)->ref_count);
+ }
+ } else {
+ wfd_sink_debug("video decodebin has parent(%s), unref it",
+ GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+
+ gst_object_unref(GST_OBJECT(parent));
+ }
+
+ wfd_sink->video_decodebin_is_linked = FALSE;
+
+ MMWFDSINK_FREEIF(wfd_sink->pipeline->v_decodebin);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
+{
+ MMWFDSinkGstElement *v_decodebin = NULL;
+ guint video_codec = WFD_VIDEO_UNKNOWN;
+ GList *element_bucket = NULL;
+ gboolean link = TRUE;
+ gint i = 0;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->pipeline->v_decodebin) {
+ wfd_sink_debug("video decodebin is already created... nothing to do");
+ return MM_ERROR_NONE;
+ }
+
+ /* check audio decodebin could be linked now */
+ switch (wfd_sink->stream_info.video_stream_info.codec) {
+ case MM_WFD_SINK_VIDEO_CODEC_H264:
+ video_codec = WFD_VIDEO_H264;
+ link = TRUE;
+ break;
+ case MM_WFD_SINK_VIDEO_CODEC_NONE:
+ default:
+ wfd_sink_debug("video decodebin could NOT be linked now, just create");
+ video_codec = wfd_sink->ini.video_codec;
+ link = FALSE;
+ break;
+ }
+
+ /* alloc handles */
+ v_decodebin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_V_D_NUM);
+ if (!v_decodebin) {
+ wfd_sink_error("failed to allocate memory for video decodebin");
+ return MM_ERROR_WFD_NO_FREE_SPACE;
+ }
+
+ memset(v_decodebin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_V_D_NUM);
+
+ /* create video decodebin */
+ v_decodebin[WFD_SINK_V_D_BIN].id = WFD_SINK_V_D_BIN;
+ v_decodebin[WFD_SINK_V_D_BIN].gst = gst_bin_new("video_decodebin");
+ if (!v_decodebin[WFD_SINK_V_D_BIN].gst) {
+ wfd_sink_error("failed to create video decodebin");
+ goto CREATE_ERROR;
+ }
+
+ /* create queue */
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_QUEUE, "queue", "video_queue", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_QUEUE].gst, "sink");
+ if (v_decodebin[WFD_SINK_V_D_QUEUE].gst)
+ __mm_wfd_sink_prepare_queue(wfd_sink, v_decodebin[WFD_SINK_V_D_QUEUE].gst);
+
+ /* create hdcp */
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_HDCP, wfd_sink->ini.name_of_video_hdcp, "video_hdcp", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_HDCP].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_HDCP].gst, "src");
+
+ if (video_codec & WFD_VIDEO_H264) {
+ /* create parser */
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_PARSE, wfd_sink->ini.name_of_video_parser, "video_parser", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_PARSE].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_PARSE].gst, "src");
+
+ /* create capssetter */
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_CAPSSETTER, wfd_sink->ini.name_of_video_capssetter, "video_capssetter", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_CAPSSETTER].gst, "src");
+
+ /* create dec */
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_DEC, wfd_sink->ini.name_of_video_decoder, "video_dec", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_DEC].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_DEC].gst, "src");
+ if (v_decodebin[WFD_SINK_V_D_DEC].gst) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_videodec(wfd_sink, v_decodebin[WFD_SINK_V_D_DEC].gst)) {
+ wfd_sink_error("failed to set video decoder property...");
+ goto CREATE_ERROR;
+ }
+ }
+ }
+
+ g_list_free(element_bucket);
+
+ /* take it */
+ wfd_sink->pipeline->v_decodebin = v_decodebin;
+
+ /* link video decodebin if video codec is fixed */
+ if (link) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_link_video_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to link video decodebin, destroy video decodebin");
+ __mm_wfd_sink_destroy_video_decodebin(wfd_sink);
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+ /* ERRORS */
+CREATE_ERROR:
+ wfd_sink_error("failed to create video decodebin, releasing all");
+
+ g_list_free(element_bucket);
+
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_V_D_NUM; i++) { /* NOTE : skip bin */
+ if (v_decodebin != NULL && v_decodebin[i].gst) {
+ GstObject *parent = NULL;
+ parent = gst_element_get_parent(v_decodebin[i].gst);
+
+ if (!parent) {
+ gst_object_unref(GST_OBJECT(v_decodebin[i].gst));
+ v_decodebin[i].gst = NULL;
+ } else {
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+
+ /* release video decodebin with it's childs */
+ if (v_decodebin != NULL && v_decodebin[WFD_SINK_V_D_BIN].gst)
+ gst_object_unref(GST_OBJECT(v_decodebin[WFD_SINK_V_D_BIN].gst));
+
+ MMWFDSINK_FREEIF(v_decodebin);
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+static int __mm_wfd_sink_destroy_video_sinkbin(mm_wfd_sink_t *wfd_sink)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ MMWFDSinkGstElement *v_sinkbin = NULL;
+ GstObject *parent = NULL;
+ int i;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->pipeline &&
+ wfd_sink->pipeline->v_sinkbin &&
+ wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+ v_sinkbin = wfd_sink->pipeline->v_sinkbin;
+ } else {
+ wfd_sink_debug("video sinkbin is not created, nothing to destroy");
+ return MM_ERROR_NONE;
+ }
+
+
+ parent = gst_element_get_parent(v_sinkbin[WFD_SINK_V_S_BIN].gst);
+ if (!parent) {
+ wfd_sink_debug("video sinkbin has no parent.. need to relase by itself");
+
+ if (GST_STATE(v_sinkbin[WFD_SINK_V_S_BIN].gst) >= GST_STATE_READY) {
+ wfd_sink_debug("try to change state of video sinkbin to NULL");
+ ret = gst_element_set_state(v_sinkbin[WFD_SINK_V_S_BIN].gst, GST_STATE_NULL);
+ if (ret != GST_STATE_CHANGE_SUCCESS) {
+ wfd_sink_error("failed to change state of video sinkbin to NULL");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_V_S_NUM; i++) { /* NOTE : skip bin */
+ if (v_sinkbin[i].gst) {
+ parent = gst_element_get_parent(v_sinkbin[i].gst);
+ if (!parent) {
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
+ ((GObject *) v_sinkbin[i].gst)->ref_count);
+ gst_object_unref(GST_OBJECT(v_sinkbin[i].gst));
+ v_sinkbin[i].gst = NULL;
+ } else {
+ wfd_sink_debug("unref %s(current ref %d)",
+ GST_STR_NULL(GST_ELEMENT_NAME(v_sinkbin[i].gst)),
+ ((GObject *) v_sinkbin[i].gst)->ref_count);
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+ /* release video sinkbin with it's childs */
+ if (v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+ gst_object_unref(GST_OBJECT(v_sinkbin[WFD_SINK_V_S_BIN].gst));
+ }
+ } else {
+ wfd_sink_debug("video sinkbin has parent(%s), unref it ",
+ GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+
+ gst_object_unref(GST_OBJECT(parent));
+ }
+
+ MMWFDSINK_FREEIF(wfd_sink->pipeline->v_sinkbin);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
+{
+ MMWFDSinkGstElement *first_element = NULL;
+ MMWFDSinkGstElement *v_sinkbin = NULL;
+ GList *element_bucket = NULL;
+ GstPad *pad = NULL;
+ GstPad *ghostpad = NULL;
+ gint i = 0;
+ gint surface_type = MM_DISPLAY_SURFACE_OVERLAY;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* alloc handles */
+ v_sinkbin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_V_S_NUM);
+ if (!v_sinkbin) {
+ wfd_sink_error("failed to allocate memory for video sinkbin");
+ return MM_ERROR_WFD_NO_FREE_SPACE;
+ }
+
+ memset(v_sinkbin, 0, sizeof(MMWFDSinkGstElement) * WFD_SINK_V_S_NUM);
+
+ /* create video sinkbin */
+ v_sinkbin[WFD_SINK_V_S_BIN].id = WFD_SINK_V_S_BIN;
+ v_sinkbin[WFD_SINK_V_S_BIN].gst = gst_bin_new("video_sinkbin");
+ if (!v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+ wfd_sink_error("failed to create video sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ /* create convert */
+ MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_CONVERT, wfd_sink->ini.name_of_video_converter, "video_convert", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_CONVERT].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_CONVERT].gst, "src");
+
+ /* create filter */
+ MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_FILTER, wfd_sink->ini.name_of_video_filter, "video_filter", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_FILTER].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_FILTER].gst, "src");
+ if (v_sinkbin[WFD_SINK_V_S_FILTER].gst) {
+ GstCaps *caps = NULL;
+ caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "SN12", NULL);
+ g_object_set(G_OBJECT(v_sinkbin[WFD_SINK_V_S_FILTER].gst), "caps", caps, NULL);
+ gst_object_unref(GST_OBJECT(caps));
+ }
+
+ /* create sink */
+ mm_attrs_get_int_by_name(wfd_sink->attrs, "display_surface_type", &surface_type);
+
+ if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
+ MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_SINK, wfd_sink->ini.name_of_video_sink, "video_sink", TRUE);
+ } else if (surface_type == MM_DISPLAY_SURFACE_EVAS) {
+ MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_SINK, wfd_sink->ini.name_of_video_evas_sink, "video_sink", TRUE);
+ } else {
+ wfd_sink_error("failed to set video sink....");
+ goto CREATE_ERROR;
+ }
+
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_SINK].gst, "sink");
+ if (v_sinkbin[WFD_SINK_V_S_SINK].gst) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_videosink(wfd_sink, v_sinkbin[WFD_SINK_V_S_SINK].gst)) {
+ wfd_sink_error("failed to set video sink property....");
+ goto CREATE_ERROR;
+ }
+ }
+
+ /* adding created elements to video sinkbin */
+ if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(v_sinkbin[WFD_SINK_V_S_BIN].gst), element_bucket, FALSE)) {
+ wfd_sink_error("failed to add elements to video sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ /* linking elements in the bucket by added order. */
+ if (__mm_wfd_sink_gst_element_link_bucket(element_bucket) == -1) {
+ wfd_sink_error("failed to link elements of the video sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ /* get first element's sinkpad for creating ghostpad */
+ first_element = (MMWFDSinkGstElement *)g_list_nth_data(element_bucket, 0);
+ if (!first_element) {
+ wfd_sink_error("failed to get first element of the video sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
+ if (!pad) {
+ wfd_sink_error("failed to get pad from first element(%s) of the video sinkbin",
+ GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
+ goto CREATE_ERROR;
+ }
+
+ ghostpad = gst_ghost_pad_new("sink", pad);
+ if (!ghostpad) {
+ wfd_sink_error("failed to create ghostpad of the video sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ if (FALSE == gst_element_add_pad(v_sinkbin[WFD_SINK_V_S_BIN].gst, ghostpad)) {
+ wfd_sink_error("failed to add ghostpad to video sinkbin");
+ goto CREATE_ERROR;
+ }
+
+ gst_object_unref(GST_OBJECT(pad));
+
+ g_list_free(element_bucket);
+
+
+ /* take it */
+ wfd_sink->pipeline->v_sinkbin = v_sinkbin;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+ /* ERRORS */
+CREATE_ERROR:
+ wfd_sink_error("failed to create video sinkbin, releasing all");
+
+ if (pad)
+ gst_object_unref(GST_OBJECT(pad));
+ pad = NULL;
+
+ if (ghostpad)
+ gst_object_unref(GST_OBJECT(ghostpad));
+ ghostpad = NULL;
+
+ g_list_free(element_bucket);
+
+ /* release element which are not added to bin */
+ for (i = 1; i < WFD_SINK_V_S_NUM; i++) { /* NOTE : skip bin */
+ if (v_sinkbin != NULL && v_sinkbin[i].gst) {
+ GstObject *parent = NULL;
+ parent = gst_element_get_parent(v_sinkbin[i].gst);
+
+ if (!parent) {
+ gst_object_unref(GST_OBJECT(v_sinkbin[i].gst));
+ v_sinkbin[i].gst = NULL;
+ } else {
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+ }
+
+ /* release video sinkbin with it's childs */
+ if (v_sinkbin != NULL && v_sinkbin[WFD_SINK_V_S_BIN].gst)
+ gst_object_unref(GST_OBJECT(v_sinkbin[WFD_SINK_V_S_BIN].gst));
+
+ MMWFDSINK_FREEIF(v_sinkbin);
+
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* cleanup gst stuffs */
+ if (wfd_sink->pipeline) {
+ MMWFDSinkGstElement *mainbin = wfd_sink->pipeline->mainbin;
+
+ if (mainbin) {
+ ret = gst_element_set_state(mainbin[WFD_SINK_M_PIPE].gst, GST_STATE_NULL);
+ if (ret != GST_STATE_CHANGE_SUCCESS) {
+ wfd_sink_error("failed to change state of mainbin to NULL");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_destroy_video_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to destroy video decodebin");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_destroy_audio_decodebin(wfd_sink)) {
+ wfd_sink_error("failed to destroy audio decodebin");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_destroy_video_sinkbin(wfd_sink)) {
+ wfd_sink_error("failed to destroy video sinkbin");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_destroy_audio_sinkbin(wfd_sink)) {
+ wfd_sink_error("failed to destroy audio sinkbin");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ gst_object_unref(GST_OBJECT(mainbin[WFD_SINK_M_PIPE].gst));
+
+ MMWFDSINK_FREEIF(mainbin);
+ }
+
+ MMWFDSINK_FREEIF(wfd_sink->pipeline);
+ }
+
+ wfd_sink->audio_decodebin_is_linked = FALSE;
+ wfd_sink->video_decodebin_is_linked = FALSE;
+ wfd_sink->need_to_reset_basetime = FALSE;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+static void
+__mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink)
+{
+ GstIterator *iter = NULL;
+ gboolean done = FALSE;
+
+ GstElement *item = NULL;
+ GstElementFactory *factory = NULL;
+
+ GstState state = GST_STATE_VOID_PENDING;
+ GstState pending = GST_STATE_VOID_PENDING;
+ GstClockTime time = 200 * GST_MSECOND;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_if_fail(wfd_sink &&
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+
+ iter = gst_bin_iterate_recurse(GST_BIN(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst));
+
+ if (iter != NULL) {
+ while (!done) {
+ switch (gst_iterator_next(iter, (gpointer)&item)) {
+ case GST_ITERATOR_OK:
+ gst_element_get_state(GST_ELEMENT(item), &state, &pending, time);
+
+ factory = gst_element_get_factory(item) ;
+ if (factory) {
+ wfd_sink_error("%s:%s : From:%s To:%s refcount : %d",
+ GST_STR_NULL(GST_OBJECT_NAME(factory)),
+ GST_STR_NULL(GST_ELEMENT_NAME(item)),
+ gst_element_state_get_name(state),
+ gst_element_state_get_name(pending),
+ GST_OBJECT_REFCOUNT_VALUE(item));
+ }
+ gst_object_unref(item);
+ break;
+ case GST_ITERATOR_RESYNC:
+ gst_iterator_resync(iter);
+ break;
+ case GST_ITERATOR_ERROR:
+ done = TRUE;
+ break;
+ case GST_ITERATOR_DONE:
+ done = TRUE;
+ break;
+ default:
+ done = TRUE;
+ break;
+ }
+ }
+ }
+
+ item = GST_ELEMENT_CAST(wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
+
+ gst_element_get_state(GST_ELEMENT(item), &state, &pending, time);
+
+ factory = gst_element_get_factory(item) ;
+ if (factory) {
+ wfd_sink_error("%s:%s : From:%s To:%s refcount : %d",
+ GST_OBJECT_NAME(factory),
+ GST_ELEMENT_NAME(item),
+ gst_element_state_get_name(state),
+ gst_element_state_get_name(pending),
+ GST_OBJECT_REFCOUNT_VALUE(item));
+ }
+
+ if (iter)
+ gst_iterator_free(iter);
+
+ wfd_sink_debug_fleave();
+
+ return;
+}
+
+const gchar * _mm_wfds_sink_get_state_name(MMWFDSinkStateType state)
+{
+ switch (state) {
+ case MM_WFD_SINK_STATE_NONE:
+ return "NONE";
+ case MM_WFD_SINK_STATE_NULL:
+ return "NULL";
+ case MM_WFD_SINK_STATE_PREPARED:
+ return "PREPARED";
+ case MM_WFD_SINK_STATE_CONNECTED:
+ return "CONNECTED";
+ case MM_WFD_SINK_STATE_PLAYING:
+ return "PLAYING";
+ case MM_WFD_SINK_STATE_PAUSED:
+ return "PAUSED";
+ case MM_WFD_SINK_STATE_DISCONNECTED:
+ return "DISCONNECTED";
+ default:
+ return "INVAID";
+ }
+}
+
+static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint *CEA_resolution, guint *VESA_resolution, guint *HH_resolution)
+{
+ if (resolution == MM_WFD_SINK_RESOLUTION_UNKNOWN) return;
+
+ *CEA_resolution = 0;
+ *VESA_resolution = 0;
+ *HH_resolution = 0;
+
+ if (resolution & MM_WFD_SINK_RESOLUTION_1920x1080_P30)
+ *CEA_resolution |= WFD_CEA_1920x1080P30;
+
+ if (resolution & MM_WFD_SINK_RESOLUTION_1280x720_P30)
+ *CEA_resolution |= WFD_CEA_1280x720P30;
+
+ if (resolution & MM_WFD_SINK_RESOLUTION_960x540_P30)
+ *HH_resolution |= WFD_HH_960x540P30;
+
+ if (resolution & MM_WFD_SINK_RESOLUTION_864x480_P30)
+ *HH_resolution |= WFD_HH_864x480P30;
+
+ if (resolution & MM_WFD_SINK_RESOLUTION_720x480_P60)
+ *CEA_resolution |= WFD_CEA_720x480P60;
+
+ if (resolution & MM_WFD_SINK_RESOLUTION_640x480_P60)
+ *CEA_resolution |= WFD_CEA_640x480P60;
+
+ if (resolution & MM_WFD_SINK_RESOLUTION_640x360_P30)
+ *HH_resolution |= WFD_HH_640x360P30;
+}
+
+int _mm_wfd_sink_set_resolution(mm_wfd_sink_t *wfd_sink, MMWFDSinkResolution resolution)
+{
+ MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+ MMWFDSINK_PRINT_STATE(wfd_sink);
+ cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
+ if (cur_state != MM_WFD_SINK_STATE_NULL) {
+ wfd_sink_error("This function must be called when MM_WFD_SINK_STATE_NULL");
+ return MM_ERROR_WFD_INVALID_STATE;
+ }
+
+ wfd_sink->supportive_resolution = resolution;
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
--- /dev/null
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
+ * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "mm_wfd_sink_util.h"
+#include <stdio.h>
+#include <tzplatform_config.h>
+
+#define DUMP_TS_DATA_PATH tzplatform_mkpath(TZ_SYS_VAR, "tmp/")
+
+static GstPadProbeReturn
+_mm_wfd_sink_util_dump(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
+{
+ gint8 *data = NULL;
+ gint size = 0;
+ FILE *f = NULL;
+ char buf[256] = {0, };
+ char path[256] = {0, };
+ GstElement * parent = NULL;
+
+ parent = gst_pad_get_parent_element(pad);
+ if (parent == NULL) {
+ wfd_sink_error("The parent of pad is NULL.");
+ return GST_PAD_PROBE_OK;
+ }
+
+ snprintf(path, sizeof(path), "%s%s_%s.ts", DUMP_TS_DATA_PATH, gst_element_get_name(parent), gst_pad_get_name(pad));
+ gst_object_unref(parent);
+
+ if (info && info->type & GST_PAD_PROBE_TYPE_BUFFER) {
+ GstMapInfo buf_info;
+ GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
+
+ gst_buffer_map(buffer, &buf_info, GST_MAP_READ);
+
+ wfd_sink_debug("got buffer %p with size %d", buffer, buf_info.size);
+ data = (gint8 *)(buf_info.data);
+ size = buf_info.size;
+ f = fopen(path, "a");
+ if (f == NULL) {
+ strerror_r(errno, buf, sizeof(buf));
+ wfd_sink_error("failed to fopen! : %s", buf);
+ return GST_PAD_PROBE_OK;
+ }
+ fwrite(data, size, 1, f);
+ fclose(f);
+ gst_buffer_unmap(buffer, &buf_info);
+ }
+
+ return GST_PAD_PROBE_OK;
+}
+
+static GstPadProbeReturn
+_mm_wfd_sink_util_pad_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
+{
+ GstElement *parent = NULL;
+
+ wfd_sink_return_val_if_fail(info &&
+ info->type != GST_PAD_PROBE_TYPE_INVALID,
+ GST_PAD_PROBE_DROP);
+ wfd_sink_return_val_if_fail(pad, GST_PAD_PROBE_DROP);
+
+ parent = (GstElement *)gst_object_get_parent(GST_OBJECT(pad));
+ if (!parent) {
+ wfd_sink_error("failed to get parent of pad");
+ return GST_PAD_PROBE_DROP;
+ }
+
+ if (info->type & GST_PAD_PROBE_TYPE_BUFFER) {
+ GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
+ /* show name and timestamp */
+ wfd_sink_debug("BUFFER PROBE : %s:%s : %u:%02u:%02u.%09u (%"G_GSSIZE_FORMAT" bytes)\n",
+ GST_STR_NULL(GST_ELEMENT_NAME(parent)),
+ GST_STR_NULL(GST_PAD_NAME(pad)),
+ GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)),
+ gst_buffer_get_size(buffer));
+ } else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM ||
+ info->type & GST_PAD_PROBE_TYPE_EVENT_UPSTREAM ||
+ info->type & GST_PAD_PROBE_TYPE_EVENT_FLUSH ||
+ info->type & GST_PAD_PROBE_TYPE_EVENT_BOTH) {
+ GstEvent *event = gst_pad_probe_info_get_event(info);
+
+ /* show name and event type */
+ wfd_sink_debug("EVENT PROBE : %s:%s : %s\n",
+ GST_STR_NULL(GST_ELEMENT_NAME(parent)),
+ GST_STR_NULL(GST_PAD_NAME(pad)),
+ GST_EVENT_TYPE_NAME(event));
+
+ if (GST_EVENT_TYPE(event) == GST_EVENT_SEGMENT) {
+ const GstSegment *segment = NULL;
+ gst_event_parse_segment(event, &segment);
+ if (segment)
+ wfd_sink_debug("NEWSEGMENT : %" GST_TIME_FORMAT
+ " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT " \n",
+ GST_TIME_ARGS(segment->start), GST_TIME_ARGS(segment->stop),
+ GST_TIME_ARGS(segment->time));
+ }
+ }
+
+ if (parent)
+ gst_object_unref(parent);
+
+ return GST_PAD_PROBE_OK;
+}
+
+void
+mm_wfd_sink_util_add_pad_probe(GstPad *pad, GstElement *element, const gchar *pad_name)
+{
+ GstPad *probe_pad = NULL;
+
+ if (!pad) {
+ if (element && pad_name)
+ probe_pad = gst_element_get_static_pad(element, pad_name);
+ } else {
+ probe_pad = pad;
+ gst_object_ref(probe_pad);
+ }
+
+ if (probe_pad) {
+ wfd_sink_debug("add pad(%s) probe", GST_STR_NULL(GST_PAD_NAME(probe_pad)));
+ gst_pad_add_probe(probe_pad, GST_PAD_PROBE_TYPE_DATA_BOTH, _mm_wfd_sink_util_pad_probe_cb, (gpointer)NULL, NULL);
+ gst_object_unref(probe_pad);
+ }
+}
+
+void
+mm_wfd_sink_util_add_pad_probe_for_data_dump(GstElement *element, const gchar *pad_name)
+{
+ GstPad *probe_pad = NULL;
+
+ if (element && pad_name)
+ probe_pad = gst_element_get_static_pad(element, pad_name);
+
+ if (probe_pad) {
+ wfd_sink_debug("add pad(%s) probe", GST_STR_NULL(GST_PAD_NAME(probe_pad)));
+ gst_pad_add_probe(probe_pad, GST_PAD_PROBE_TYPE_BUFFER, _mm_wfd_sink_util_dump, (gpointer)NULL, NULL);
+ gst_object_unref(probe_pad);
+ }
+}
+
+static GstPadProbeReturn
+_mm_wfd_sink_util_check_first_buffer_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
+{
+ GstElement *parent = NULL;
+ GstBuffer *buffer = NULL;
+ guint *probe_id = (guint *)user_data;
+
+ wfd_sink_return_val_if_fail(pad, GST_PAD_PROBE_DROP);
+ wfd_sink_return_val_if_fail(info, GST_PAD_PROBE_DROP);
+
+ parent = GST_ELEMENT_CAST(gst_object_get_parent(GST_OBJECT(pad)));
+ if (parent == NULL) {
+ wfd_sink_error("The parent of pad is NULL.");
+ return GST_PAD_PROBE_DROP;
+ }
+
+ buffer = gst_pad_probe_info_get_buffer(info);
+
+ wfd_sink_debug("FIRST BUFFER PROBE : %s:%s : %u:%02u:%02u.%09u (%"G_GSSIZE_FORMAT" bytes)\n",
+ GST_STR_NULL(GST_ELEMENT_NAME(parent)), GST_STR_NULL(GST_PAD_NAME(pad)),
+ GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)), gst_buffer_get_size(buffer));
+
+ if (probe_id && *probe_id > 0) {
+ wfd_sink_debug("remove buffer probe[%d]\n", *probe_id);
+ gst_pad_remove_probe(pad, *probe_id);
+
+ MMWFDSINK_FREEIF(probe_id);
+ }
+
+ if (parent)
+ gst_object_unref(parent);
+
+ return GST_PAD_PROBE_REMOVE;
+}
+
+void
+mm_wfd_sink_util_add_pad_probe_for_checking_first_buffer(GstPad *pad, GstElement *element, const gchar *pad_name)
+{
+ GstPad *probe_pad = NULL;
+ guint *probe_id = NULL;
+
+ if (!pad) {
+ if (element && pad_name)
+ probe_pad = gst_element_get_static_pad(element, pad_name);
+ } else {
+ probe_pad = pad;
+ gst_object_ref(probe_pad);
+ }
+
+ if (probe_pad) {
+ probe_id = g_malloc0(sizeof(guint));
+ if (!probe_id) {
+ wfd_sink_error("failed to allocate memory for probe id\n");
+ gst_object_unref(probe_pad);
+ return;
+ }
+
+ *probe_id = gst_pad_add_probe(probe_pad, GST_PAD_PROBE_TYPE_BUFFER, _mm_wfd_sink_util_check_first_buffer_cb, (gpointer)probe_id, NULL);
+ wfd_sink_debug("add pad(%s) probe, %d", GST_STR_NULL(GST_PAD_NAME(probe_pad)), *probe_id);
+
+ gst_object_unref(probe_pad);
+ }
+
+ return;
+}
+
--- /dev/null
+/*
+* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <glib.h>
+#include <string.h>
+#include <mm_error.h>
+#include <wayland-client.h>
+#include <tizen-extension-client-protocol.h>
+
+#include "mm_wfd_sink_dlog.h"
+#include "mm_wfd_sink_wayland.h"
+
+#define goto_if_fail(expr,label) \
+{ \
+ if (!(expr)) { \
+ wfd_sink_error(" failed [%s]\n", #expr); \
+ goto label; \
+ } \
+}
+
+void mm_wfd_sink_handle_resource_id(void *data, struct tizen_resource *tizen_resource, uint32_t id)
+{
+ unsigned int *wl_surface_id = data;
+
+ *wl_surface_id = id;
+
+ wfd_sink_debug("[CLIENT] got wl_surface_id(%d) from server\n", id);
+}
+
+static const struct tizen_resource_listener tz_resource_listener =
+{
+ mm_wfd_sink_handle_resource_id,
+};
+
+static void
+mm_wfd_sink_handle_global(void *data, struct wl_registry *registry,
+ uint32_t name, const char *interface, uint32_t version)
+{
+ return_if_fail (data != NULL);
+ wl_client *wlclient = data;
+
+ if (strcmp(interface, "tizen_surface") == 0)
+ {
+ wfd_sink_debug("binding tizen_surface");
+ wlclient->tz_surface = wl_registry_bind(registry, name, &tizen_surface_interface, version);
+ return_if_fail (wlclient->tz_surface != NULL);
+ }
+}
+
+static void mm_wfd_sink_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name)
+{
+ wfd_sink_debug("wl_registry_handle_global_remove");
+}
+
+static const struct wl_registry_listener registry_listener =
+{
+ mm_wfd_sink_handle_global,
+ mm_wfd_sink_handle_global_remove
+};
+
+int mm_wfd_sink_wlclient_create (wl_client ** wlclient)
+{
+ wl_client *ptr = NULL;
+
+ ptr = g_malloc0 (sizeof (wl_client));
+ if (!ptr) {
+ wfd_sink_error ("Cannot allocate memory for wlclient\n");
+ goto ERROR;
+ } else {
+ *wlclient = ptr;
+ wfd_sink_debug ("Success create wlclient(%p)", *wlclient);
+ }
+ return MM_ERROR_NONE;
+
+ERROR:
+ *wlclient = NULL;
+ return MM_ERROR_WFD_NO_FREE_SPACE;
+}
+
+
+int mm_wfd_sink_wlclient_get_wl_window_wl_surface_id (wl_client * wlclient, struct wl_surface *surface, struct wl_display *display)
+{
+ goto_if_fail (wlclient != NULL, failed);
+ goto_if_fail (surface != NULL, failed);
+ goto_if_fail (display != NULL, failed);
+
+ unsigned int wl_surface_id = 0;
+
+ wlclient->display = display;
+ goto_if_fail (wlclient->display != NULL, failed);
+
+ wlclient->registry = wl_display_get_registry(wlclient->display);
+ goto_if_fail (wlclient->registry != NULL, failed);
+
+ wl_registry_add_listener(wlclient->registry, ®istry_listener, wlclient);
+ wl_display_dispatch(wlclient->display);
+ wl_display_roundtrip(wlclient->display);
+
+ /* check global objects */
+ goto_if_fail (wlclient->tz_surface != NULL, failed);
+
+ /* Get wl_surface_id which is unique in a entire systemw. */
+ wlclient->tz_resource = tizen_surface_get_tizen_resource(wlclient->tz_surface, surface);
+ goto_if_fail (wlclient->tz_resource != NULL, failed);
+
+ tizen_resource_add_listener(wlclient->tz_resource, &tz_resource_listener, &wl_surface_id);
+ wl_display_roundtrip(wlclient->display);
+ goto_if_fail (wl_surface_id > 0, failed);
+
+ mm_wfd_sink_wlclient_finalize(wlclient);
+
+ return wl_surface_id;
+
+failed:
+ wfd_sink_error ("Failed to get wl_surface_id");
+
+ return 0;
+}
+
+void mm_wfd_sink_wlclient_finalize (wl_client * wlclient)
+{
+ wfd_sink_debug ("start finalize wlclient");
+ return_if_fail (wlclient != NULL)
+
+ if (wlclient->tz_surface)
+ tizen_surface_destroy(wlclient->tz_surface);
+
+ if (wlclient->tz_resource)
+ tizen_resource_destroy(wlclient->tz_resource);
+
+ /* destroy registry */
+ if (wlclient->registry)
+ wl_registry_destroy(wlclient->registry);
+ return;
+}