#include <gst/gst.h>
#include <gst/video/videooverlay.h>
#include <Elementary.h>
-#include <Ecore_Wayland.h>
+#include <Ecore_Wl2.h>
+#include <sys/syscall.h>
#include "mm_wfd_sink_util.h"
#include "mm_wfd_sink_priv.h"
#include "mm_wfd_sink_dlog.h"
#include "mm_wfd_sink_enum.h"
#include "mm_wfd_sink_wayland.h"
+#include "mm_wfd_sink_config.h"
+
+#define PRINT_WFD_REF_COUNT(wfd_sink)\
+ do {\
+ wfd_sink_debug("PRINT WFD REF COUNT");\
+ __mm_wfd_sink_print_ref_count(wfd_sink);\
+ } while (0);
/* 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);
+static gboolean _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data);
/* 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)
+static int
+__resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
+ void *user_data)
+{
+ mm_wfd_sink_t *wfdsink = NULL;
+ MMWFDSinkResourceType res_idx = MM_WFD_SINK_RESOURCE_TYPE_MAX;
+
+ wfd_sink_debug_fenter();
+
+ if (!user_data) {
+ wfd_sink_error("user_data is null");
+ return FALSE;
+ }
+
+ wfdsink = (mm_wfd_sink_t *)user_data;
+
+ wfdsink->interrupted_by_resource = TRUE;
+
+ wfd_sink_debug("resource is interrupted. resource would be released after destroying");
+
+ MMWFDSINK_CMD_LOCK(wfdsink);
+ if (_mm_wfd_sink_disconnect(wfdsink) != MM_ERROR_NONE)
+ wfd_sink_error("failed to disconnect");
+
+ if (_mm_wfd_sink_unprepare(wfdsink) != MM_ERROR_NONE)
+ wfd_sink_error("failed to unprepare");
+ for (res_idx = MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MM_WFD_SINK_RESOURCE_TYPE_MAX; res_idx++) {
+ wfdsink->hw_resource[res_idx] = NULL;
+ }
+ MMWFDSINK_CMD_UNLOCK(wfdsink);
+
+ wfd_sink_debug_fleave();
+ return TRUE; /* release all the resources */
+}
+
+static int __mm_wfd_sink_acquire_hw_resource (mm_wfd_sink_t* wfd_sink, MMWFDSinkResourceType type)
+{
+ int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ mm_resource_manager_res_type_e rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
+
+ switch (type) {
+ case MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER:
+ rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER;
+ break;
+ case MM_WFD_SINK_RESOURCE_TYPE_VIDEO_OVERLAY:
+ rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY;
+ break;
+ default:
+ wfd_sink_error("invalid wfd sink resource type %d", type);
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ if (wfd_sink->hw_resource[type] != NULL) {
+ wfd_sink_debug("[%d type] resource was already acquired", type);
+ return MM_ERROR_NONE;
+ }
+
+ wfd_sink_debug("mark for acquire [%d type] resource", type);
+ rm_ret = mm_resource_manager_mark_for_acquire(wfd_sink->resource_manager,
+ rm_res_type, MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &wfd_sink->hw_resource[type]);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ wfd_sink_error("failed to mark resource for acquire, ret(0x%x)", rm_ret);
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ rm_ret = mm_resource_manager_commit(wfd_sink->resource_manager);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ wfd_sink_error("failed to commit of resource, ret(0x%x)", rm_ret);
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+}
+
+static int __mm_wfd_sink_release_hw_resource(mm_wfd_sink_t *wfd_sink, MMWFDSinkResourceType type)
+{
+ int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ if (wfd_sink->hw_resource[type] == NULL) {
+ wfd_sink_debug("there is no acquired [%d type] resource", type);
+ return MM_ERROR_NONE;
+ }
+
+ wfd_sink_debug("mark for release [%d type] resource", type);
+ rm_ret = mm_resource_manager_mark_for_release(wfd_sink->resource_manager, wfd_sink->hw_resource[type]);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ wfd_sink_error("failed to mark resource for release, ret(0x%x)", rm_ret);
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ wfd_sink->hw_resource[type] = NULL;
+
+ rm_ret = mm_resource_manager_commit(wfd_sink->resource_manager);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ wfd_sink_error("failed to commit of resource, ret(0x%x)", rm_ret);
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+}
+
+int _mm_wfd_sink_create(mm_wfd_sink_t **wfd_sink, const char *ini_path)
{
int result = MM_ERROR_NONE;
wfd_sink_debug_fenter();
wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+ if (ini_path == NULL) {
+ ini_path = MM_WFD_SINK_INI_DEFAULT_PATH;
+ wfd_sink_debug("The wfd ini file path is set as defalut[%s]", ini_path);
+ }
mm_wfd_sink_t *new_wfd_sink = NULL;
return MM_ERROR_WFD_NO_FREE_SPACE;
}
+ /* initialize resource manager */
+ if (mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
+ __resource_release_cb, new_wfd_sink, &new_wfd_sink->resource_manager)
+ != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ wfd_sink_error("failed to initialize resource manager");
+ MMWFDSINK_FREEIF(new_wfd_sink);
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
/* Initialize gstreamer related */
new_wfd_sink->attrs = 0;
/* Initialize video resolution */
new_wfd_sink->supportive_resolution = MM_WFD_SINK_RESOLUTION_UNKNOWN;
+ /* Initialize coulped sink information */
+ new_wfd_sink->coupled_sink_address = NULL;
+ new_wfd_sink->coupled_sink_status = MM_WFD_COUPLED_SINK_STATUS_NOT_COUPLED;
+
+ /* In case of R2 sink, it would be TRUE */
+ new_wfd_sink->is_coupled_sink_supported = FALSE;
+
/* construct attributes */
new_wfd_sink->attrs = _mmwfd_construct_attribute((MMHandleType)new_wfd_sink);
if (!new_wfd_sink->attrs) {
- MMWFDSINK_FREEIF(new_wfd_sink);
+ result = MM_ERROR_WFD_INTERNAL;
wfd_sink_error("failed to set attribute");
- return MM_ERROR_WFD_INTERNAL;
+ goto fail_to_attrs;
}
/* load ini for initialize */
- result = mm_wfd_sink_ini_load(&new_wfd_sink->ini);
+ result = mm_wfd_sink_ini_load(&new_wfd_sink->ini, ini_path);
if (result != MM_ERROR_NONE) {
- wfd_sink_error("failed to load ini file");
+ wfd_sink_error("failed to load ini file[%s]", ini_path);
goto fail_to_load_ini;
}
new_wfd_sink->need_to_reset_basetime = new_wfd_sink->ini.enable_reset_basetime;
mm_wfd_sink_ini_unload(&new_wfd_sink->ini);
fail_to_load_ini:
_mmwfd_deconstruct_attribute(new_wfd_sink->attrs);
+fail_to_attrs:
+ mm_resource_manager_destroy(new_wfd_sink->resource_manager);
MMWFDSINK_FREEIF(new_wfd_sink);
*wfd_sink = NULL;
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(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);
+ 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_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);
+ 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);
+ g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "request-pause", NULL);
wfd_sink_debug_fleave();
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);
+ 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);
+ g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "request-resume", NULL);
wfd_sink_debug_fleave();
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);
+ 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);
+ g_signal_emit_by_name(wfd_sink->pipeline->mainbin[WFD_SINK_M_SRC].gst, "request-close", NULL);
wfd_sink_debug_fleave();
/* set state */
__mm_wfd_sink_set_state(wfd_sink, MM_WFD_SINK_STATE_NULL);
+ if (!wfd_sink->interrupted_by_resource) {
+ int rm_ret = MM_ERROR_NONE;
+ MMWFDSinkResourceType res_idx = MM_WFD_SINK_RESOURCE_TYPE_MAX;
+
+ for (res_idx = MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MM_WFD_SINK_RESOURCE_TYPE_MAX; res_idx++) {
+ rm_ret = __mm_wfd_sink_release_hw_resource(wfd_sink, res_idx);
+ if (rm_ret != MM_ERROR_NONE)
+ wfd_sink_error("failed to release [%d] resources", res_idx);
+ }
+ }
wfd_sink_debug_fleave();
return result;
/* release attributes */
_mmwfd_deconstruct_attribute(wfd_sink->attrs);
+ /* release the others */
+ g_free(wfd_sink->coupled_sink_address);
+
+ /* release resource manager */
+ if (MM_ERROR_NONE != mm_resource_manager_destroy(wfd_sink->resource_manager)) {
+ result = MM_ERROR_WFD_INTERNAL;
+ wfd_sink_error("failed to destroy resource manager");
+ }
+
+ /* release manager thread */
if (MM_ERROR_NONE != _mm_wfd_sink_release_manager(wfd_sink)) {
+ result = MM_ERROR_WFD_INTERNAL;
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("initializing gstreamer with following parameter");
wfd_sink_debug("argc : %d", *argc);
- for (i = 0; i < *argc; i++) {
+ 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");
+ wfd_sink_error("failed to initialize gstreamer: %s",
+ err ? err->message : "unknown error occurred");
if (err)
g_error_free(err);
}
/* release */
- for (i = 0; i < *argc; i++) {
+ for (i = 0; i < *argc; i++)
MMWFDSINK_FREEIF(argv[i]);
- }
+
MMWFDSINK_FREEIF(argv);
MMWFDSINK_FREEIF(argc);
GstBusSyncReply ret = GST_BUS_PASS;
wfd_sink_return_val_if_fail(message &&
- GST_IS_MESSAGE(message) &&
- GST_MESSAGE_SRC(message),
- GST_BUS_DROP);
+ GST_IS_MESSAGE(message) &&
+ GST_MESSAGE_SRC(message),
+ GST_BUS_DROP);
+
+ wfd_sink_debug("get message %p, %s from %p, %s", message,
+ GST_MESSAGE_TYPE_NAME(message), GST_MESSAGE_SRC(message), GST_MESSAGE_SRC_NAME(message));
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;
+ 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)))
+ _mm_wfd_sink_msg_callback(bus, message, data);
+
+ ret = GST_BUS_DROP;
+ break;
+ case GST_MESSAGE_ASYNC_DONE:
+ if (GST_IS_PIPELINE(GST_MESSAGE_SRC(message)))
+ _mm_wfd_sink_msg_callback(bus, message, data);
+
+ ret = GST_BUS_DROP;
+ break;
+ default:
+ break;
+ }
+
+ if (ret == GST_BUS_DROP) {
+ gst_message_unref(message);
+ message = NULL;
}
return ret;
}
+int __mm_wfd_sink_activate_audio_stream(mm_wfd_sink_t *wfd_sink)
+{
+ GstElement *valve = NULL;
+ GstPad *sinkpad = NULL;
+ GstPad *srcpad = NULL;
+ 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_A_VALVE].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst;
+ srcpad = gst_element_get_static_pad(valve, "src");
+ if (!srcpad) {
+ wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(valve));
+ goto error;
+ }
+
+ if (gst_pad_is_linked(srcpad)) {
+ wfd_sink_debug("%s:%s is already linked",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+ goto done;
+ }
+
+ result = __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, &sinkpad);
+ if (MM_ERROR_NONE != result) {
+ wfd_sink_error("failed to prepare audio pipeline....");
+ goto error;
+ }
+
+ wfd_sink_debug("try to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+ wfd_sink_error("failed to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto error;
+ }
+
+ if (sinkpad != NULL) {
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+ }
+
+done:
+ if (srcpad != NULL) {
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+ }
+ /* drop all the audio buffers using valve */
+ g_object_set(G_OBJECT(valve), "drop", FALSE, NULL);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+error:
+ if (srcpad != NULL) {
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+ }
+
+ if (sinkpad != NULL) {
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+ }
+
+ wfd_sink_debug_fleave();
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_activate_video_stream(mm_wfd_sink_t *wfd_sink)
+{
+ GstElement *valve = NULL;
+ GstPad *sinkpad = NULL;
+ GstPad *srcpad = NULL;
+ 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_V_VALVE].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst;
+ srcpad = gst_element_get_static_pad(valve, "src");
+ if (!srcpad) {
+ wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(valve));
+ goto error;
+ }
+
+ if (gst_pad_is_linked(srcpad)) {
+ wfd_sink_debug("%s:%s is already linked",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+ goto done;
+ }
+
+ result = __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &sinkpad);
+ if (MM_ERROR_NONE != result) {
+ wfd_sink_error("failed to prepare video pipeline....");
+ goto error;
+ }
+
+ wfd_sink_debug("try to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+ wfd_sink_error("failed to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto error;
+ }
+ if (sinkpad != NULL) {
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+ }
+
+done:
+ if (srcpad != NULL) {
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+ }
+ /* drop all the video buffers using valve */
+ g_object_set(G_OBJECT(valve), "drop", FALSE, NULL);
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+error:
+ if (srcpad != NULL) {
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+ }
+
+ if (sinkpad != NULL) {
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+ }
+
+ wfd_sink_debug_fleave();
+ return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_deactivate_audio_stream(mm_wfd_sink_t *wfd_sink, gboolean unprepare)
+{
+ int ret = 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_A_VALVE].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* drop all the audio buffers using valve */
+ g_object_set(G_OBJECT(wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst), "drop", TRUE, NULL);
+
+ if (unprepare) {
+ /* unprepare audio pipeline */
+ ret = __mm_wfd_sink_unprepare_audio_pipeline(wfd_sink);
+ if (ret != MM_ERROR_NONE) {
+ wfd_sink_error("failed to unprepare audio pipeline...");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+int __mm_wfd_sink_deactivate_video_stream(mm_wfd_sink_t *wfd_sink, gboolean unprepare)
+{
+ int ret = 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_V_VALVE].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ /* drop all the video buffers using valve */
+ g_object_set(G_OBJECT(wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst), "drop", TRUE, NULL);
+
+ if (unprepare) {
+ /* unprepare video pipeline */
+ ret = __mm_wfd_sink_unprepare_video_pipeline(wfd_sink);
+ if (ret != MM_ERROR_NONE) {
+ wfd_sink_error("failed to unprepare video pipeline...");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ }
+
+ wfd_sink_debug_fleave();
+
+ return MM_ERROR_NONE;
+
+}
+
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;
+ gchar *getname = NULL;
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",
+ wfd_sink_debug("got %s(%d) from %s",
GST_STR_NULL(GST_MESSAGE_TYPE_NAME(msg)),
+ GST_MESSAGE_TYPE(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);
+ case GST_MESSAGE_ERROR: {
+ GError *error = NULL;
+ gchar *debug = NULL;
- wfd_sink_error("error : %s", error->message);
- wfd_sink_error("debug : %s", debug);
-
- MMWFDSINK_FREEIF(debug);
- g_error_free(error);
- }
- break;
+ /* get error code */
+ gst_message_parse_error(msg, &error, &debug);
- case GST_MESSAGE_WARNING: {
- char *debug = NULL;
- GError *error = NULL;
+ wfd_sink_error("error : %s", error->message);
+ wfd_sink_error("debug : %s", debug);
- gst_message_parse_warning(msg, &error, &debug);
+ MMWFDSINK_FREEIF(debug);
+ g_error_free(error);
+ }
+ break;
- wfd_sink_warning("warning : %s", error->message);
- wfd_sink_warning("debug : %s", debug);
+ case GST_MESSAGE_WARNING: {
+ char *debug = NULL;
+ GError *error = NULL;
- MMWFDSINK_FREEIF(debug);
- g_error_free(error);
- }
- break;
+ gst_message_parse_warning(msg, &error, &debug);
- 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;
- }
+ wfd_sink_error("warning : %s", error->message);
+ wfd_sink_error("debug : %s", debug);
- 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;
- }
+ 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;
+
+ /* 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));
+
+ /* we only handle messages from pipeline */
+ if (msg->src != (GstObject *)wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst)
+ break;
+
+ if (oldstate == newstate) {
+ wfd_sink_debug("pipeline reports state transition to old state");
+ 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"));
+ 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;
+ }
+ 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",
+ 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;
+ wfd_sink->clock = clock;
+ }
+ break;
- message_structure_name = gst_structure_get_name(message_structure);
- if (!message_structure_name)
- break;
+ case GST_MESSAGE_APPLICATION: {
+ const gchar *message_structure_name;
- wfd_sink_debug("message name : %s", GST_STR_NULL(message_structure_name));
- }
- break;
+ message_structure_name = gst_structure_get_name(message_structure);
+ if (!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));
- }
+ 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, "GstWFDSessionTimeout")) {
+ wfd_sink_error("Got %s, post error message", GST_STR_NULL(structure_name));
+ MMWFDSINK_POST_MESSAGE(wfd_sink,
+ MM_ERROR_WFD_INTERNAL,
+ MM_WFD_SINK_STATE_DISCONNECTED);
}
}
- 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); */
+ }
+ 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);
+ } else if (category && !strcmp(category, "coupling")) {
+ wfd_sink->coupled_sink_status = MM_WFD_COUPLED_SINK_STATUS_COUPLED;
+ wfd_sink->coupled_sink_address = g_strdup(text);
+ wfd_sink_debug("coupling info [%d : %s]", wfd_sink->coupled_sink_status, wfd_sink->coupled_sink_address);
+ __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, "pause")) {
- wfd_sink_error("got error : %s", GST_STR_NULL(text));
+ 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 if (category && !strcmp(category, "close")) {
- wfd_sink_error("got error : %s", GST_STR_NULL(text));
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+ } else if (category && !strcmp(category, "coupling")) {
+ 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;
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
+ } else {
+ wfd_sink_error("got error : %s", GST_STR_NULL(text));
}
-
- MMWFDSINK_FREEIF(category);
- MMWFDSINK_FREEIF(text);
+ break;
+ default:
+ wfd_sink_error("progress message has no type");
+ return ret;
}
- 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;
+
+ MMWFDSINK_FREEIF(category);
+ MMWFDSINK_FREEIF(text);
+ }
+ break;
+
+ case GST_MESSAGE_ASYNC_START:
+ getname = gst_element_get_name(GST_MESSAGE_SRC(msg));
+ wfd_sink_debug("GST_MESSAGE_ASYNC_START : %s", getname);
+ MMWFDSINK_FREEIF(getname);
+ break;
+ case GST_MESSAGE_ASYNC_DONE:
+ getname = gst_element_get_name(GST_MESSAGE_SRC(msg));
+ wfd_sink_debug("GST_MESSAGE_ASYNC_DONE : %s", getname);
+ MMWFDSINK_FREEIF(getname);
+ 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
+int
__mm_wfd_sink_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket, gboolean need_prepare)
{
GList *bucket = element_bucket;
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))));
+ 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))));
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))),
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT_CAST(bin))));
successful_add_count++;
}
return successful_add_count;
}
-static int
+int
__mm_wfd_sink_gst_element_link_bucket(GList *element_bucket)
{
GList *bucket = element_bucket;
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))));
+ 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))));
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst))),
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_ELEMENT(element->gst))));
return -1;
}
}
return successful_link_count;
}
-static int
+int
__mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd)
{
MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
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_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;
- 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;
+ MMWFDSINK_PENDING_STATE(wfd_sink) = MM_WFD_SINK_STATE_NONE;
+ break;
- default:
- break;
+ default:
+ break;
}
wfd_sink->cmd = cmd;
/* ERRORS */
invalid_state:
- wfd_sink_error("current state is invalid.", MMWFDSINK_STATE_GET_NAME(cur_state));
+ wfd_sink_error("current state[%s] 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)
+int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType state)
{
wfd_sink_debug_fenter();
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 */
+ /* post state message to application */
MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_NONE,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
+ MM_ERROR_NONE,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
/* print state */
MMWFDSINK_PRINT_STATE(wfd_sink);
return MM_ERROR_NONE;
}
-static int
+int
__mm_wfd_sink_set_pipeline_state(mm_wfd_sink_t *wfd_sink, GstState state, gboolean async)
{
GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
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->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_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));
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);
+ 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);
}
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));
+ gst_element_state_get_name(cur_state),
+ gst_element_state_get_name(pending_state));
}
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->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);
}
int
-__mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
+__mm_wfd_sink_unprepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
{
- GstElement *bin = NULL;
+ GstElement *pipeline = NULL;
+ GstElement *v_decodebin = NULL;
+ GstElement *v_sinkbin = NULL;
+ GstPad *sinkpad = NULL;
+ GstPad *srcpad = NULL;
+ int ret = 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,
- MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->stream_info.video_stream_info.codec == MM_WFD_SINK_VIDEO_CODEC_NONE) {
+ wfd_sink_debug("Skip unprepare video pipeline for none audio codec.");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
+
+ PRINT_WFD_REF_COUNT(wfd_sink);
+ wfd_sink_error("No-error:unprepare video sink bin");
+ if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+ v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+
+ if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_sinkbin)))) {
+ sinkpad = gst_element_get_static_pad(v_sinkbin, "sink");
+ if (!sinkpad) {
+ wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(v_sinkbin));
+ goto ERROR;
+ }
+
+ if (gst_pad_is_linked(sinkpad)) {
+ srcpad = gst_pad_get_peer(sinkpad);
+ if (!srcpad) {
+ wfd_sink_error("failed to get peer pad of %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+
+ wfd_sink_error("try to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (!gst_pad_unlink(srcpad, sinkpad)) {
+ wfd_sink_error("failed to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ } else {
+ wfd_sink_debug("video sinkbin's sinkpad is not linked, no need to unlink it");
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+
+ wfd_sink_error("try to remove %s from %s",
+ GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+
+ gst_object_ref(v_sinkbin);
+ if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(v_sinkbin))) {
+ wfd_sink_error("failed to remove %s from %s",
+ GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+ goto ERROR;
+ }
+
+ gst_object_unref(pipeline);
+ pipeline = NULL;
+ }
+
+ ret = __mm_wfd_sink_destroy_video_sinkbin(wfd_sink);
+ if (ret != MM_ERROR_NONE) {
+ wfd_sink_error("failed to destroy video sinkbin");
+ goto ERROR;
+ }
+ }
+ PRINT_WFD_REF_COUNT(wfd_sink);
+
+ wfd_sink_error("No-error:unprepare video decode bin");
+ if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+ v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+
+ if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_decodebin)))) {
+ sinkpad = gst_element_get_static_pad(v_decodebin, "sink");
+ if (!sinkpad) {
+ wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(v_decodebin));
+ goto ERROR;
+ }
+
+ if (gst_pad_is_linked(sinkpad)) {
+ srcpad = gst_pad_get_peer(sinkpad);
+ if (!srcpad) {
+ wfd_sink_error("failed to get peer pad of %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+
+ wfd_sink_error("try to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (!gst_pad_unlink(srcpad, sinkpad)) {
+ wfd_sink_error("failed to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ } else {
+ wfd_sink_debug("video decodebin's sinkpad is not linked, no need to unlink it");
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+
+ srcpad = gst_element_get_static_pad(v_decodebin, "src");
+ if (!srcpad) {
+ wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(v_decodebin));
+ goto ERROR;
+ }
+
+ if (gst_pad_is_linked(srcpad)) {
+ sinkpad = gst_pad_get_peer(srcpad);
+ if (!sinkpad) {
+ wfd_sink_error("failed to get peer pad of %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+ goto ERROR;
+ }
+
+ wfd_sink_error("try to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (!gst_pad_unlink(srcpad, sinkpad)) {
+ wfd_sink_error("failed to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ } else {
+ wfd_sink_debug("video decodebin's srcpad is not linked, no need to unlink it");
+ }
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+
+ wfd_sink_error("try to remove %s from %s",
+ GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+ gst_object_ref(v_decodebin);
+ if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(v_decodebin))) {
+ wfd_sink_error("failed to remove %s from %s",
+ GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+ goto ERROR;
+ }
+
+ gst_object_unref(pipeline);
+ pipeline = NULL;
+ }
+
+ ret = __mm_wfd_sink_destroy_video_decodebin(wfd_sink);
+ if (ret != MM_ERROR_NONE) {
+ wfd_sink_error("failed to destroy video decodebin");
+ goto ERROR;
+ }
+ }
+ PRINT_WFD_REF_COUNT(wfd_sink);
+
+ wfd_sink_debug_fleave();
+
+ return ret;
+
+ /* ERRORS */
+ERROR:
+ if (pipeline) {
+ gst_object_unref(pipeline);
+ pipeline = NULL;
+ }
+
+ if (sinkpad) {
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ }
+
+ if (srcpad) {
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+
+ /* 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_video_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
+{
+ GstElement *pipeline = NULL;
+ GstElement *v_decodebin = NULL;
+ GstElement *v_sinkbin = NULL;
+ GstPad *srcpad = NULL;
+ GstPad *sinkpad = 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);
+
+ if (wfd_sink->stream_info.video_stream_info.codec == MM_WFD_SINK_VIDEO_CODEC_NONE) {
+ wfd_sink_debug("Skip prepare video pipeline for none audio codec");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
/* check video decodebin is linked */
if (!wfd_sink->video_decodebin_is_linked) {
goto ERROR;
}
}
-
- /* set video decodebin state as READY */
+ /* add video decodebin to pipeline */
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");
+ v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+
+ pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_decodebin));
+ if (!pipeline) {
+ pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+ if (GST_STATE(v_decodebin) <= GST_STATE_NULL) {
+ wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(v_decodebin));
+ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(v_decodebin, GST_STATE_READY)) {
+ wfd_sink_error("failed to set state(READY) to video decodebin");
+ goto ERROR;
+ }
+ }
+
+ wfd_sink_debug("try to add %s to %s",
+ GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+ if (!gst_bin_add(GST_BIN(pipeline), GST_ELEMENT(v_decodebin))) {
+ wfd_sink_error("failed to add %s to %s",
+ GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+ goto ERROR;
+ }
+
+ wfd_sink_debug("need to sync state %s with its parent", GST_ELEMENT_NAME(v_decodebin));
+ if (!gst_element_sync_state_with_parent(GST_ELEMENT(v_decodebin))) {
+ wfd_sink_error("failed to sync %s state with parent", GST_ELEMENT_NAME(v_decodebin));
goto ERROR;
}
+ } else {
+ wfd_sink_debug("%s is already added to %s",
+ GST_ELEMENT_NAME(v_decodebin), GST_ELEMENT_NAME(pipeline));
+ gst_object_unref(pipeline);
+ pipeline = NULL;
}
} else {
wfd_sink_warning("going on without video decodebin....");
}
- /* set video sinkbin state as READY */
+ /* add video sinkbin to pipeline */
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");
+ v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+
+ pipeline = GST_ELEMENT_CAST(gst_element_get_parent(v_sinkbin));
+ if (!pipeline) {
+ pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+ /* prepare video sinkbin before adding */
+ if (GST_STATE(v_sinkbin) <= GST_STATE_NULL) {
+ wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(v_sinkbin));
+ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(v_sinkbin, GST_STATE_READY)) {
+ wfd_sink_error("failed to set state(READY) to video sinkbin");
+ goto ERROR;
+ }
+ }
+ /* add video sinkbin to pipeline */
+ wfd_sink_debug("try to add %s to %s",
+ GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+ if (!gst_bin_add(GST_BIN(pipeline), GST_ELEMENT(v_sinkbin))) {
+ wfd_sink_error("failed to add %s to %s",
+ GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+ goto ERROR;
+ }
+
+ /* sync state with parent */
+ wfd_sink_debug("need to sync state %s with its parent", GST_ELEMENT_NAME(v_sinkbin));
+ if (!gst_element_sync_state_with_parent(GST_ELEMENT(v_sinkbin))) {
+ wfd_sink_error("failed to sync %s state with parent", GST_ELEMENT_NAME(v_sinkbin));
goto ERROR;
}
+ } else {
+ wfd_sink_debug("%s is already added to %s",
+ GST_ELEMENT_NAME(v_sinkbin), GST_ELEMENT_NAME(pipeline));
+ gst_object_unref(pipeline);
+ pipeline = NULL;
}
} else {
wfd_sink_warning("going on without video sinkbin....");
}
+
+ /* link video decodebin and sinkbin */
+ if (wfd_sink->pipeline->v_decodebin && wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+ v_decodebin = wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst;
+
+ if (pad)
+ *pad = gst_element_get_static_pad(v_decodebin, "sink");
+
+ if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+
+ v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+
+ srcpad = gst_element_get_static_pad(v_decodebin, "src");
+ if (!srcpad) {
+ wfd_sink_error("faied to get srcpad from %s", GST_ELEMENT_NAME(v_decodebin));
+ goto ERROR;
+ }
+
+ if (!gst_pad_is_linked(srcpad)) {
+ sinkpad = gst_element_get_static_pad(v_sinkbin, "sink");
+ if (!sinkpad) {
+ wfd_sink_error("faied to get sinkpad from %s", GST_ELEMENT_NAME(v_sinkbin));
+ goto ERROR;
+ }
+
+ wfd_sink_debug("try to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+ wfd_sink_error("failed to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ }
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+ } else if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+ v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
+ if (pad)
+ *pad = gst_element_get_static_pad(v_sinkbin, "sink");
+ }
+
wfd_sink_debug_fleave();
return MM_ERROR_NONE;
/* ERRORS */
ERROR:
+ if (sinkpad != NULL) {
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ }
+
+ if (srcpad != NULL) {
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+
+ /* 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_unprepare_audio_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+ GstElement *pipeline = NULL;
+ GstElement *a_decodebin = NULL;
+ GstElement *a_sinkbin = NULL;
+ GstPad *sinkpad = NULL;
+ GstPad *srcpad = NULL;
+ int ret = MM_ERROR_NONE;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_val_if_fail(wfd_sink &&
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->stream_info.audio_stream_info.codec == MM_WFD_SINK_AUDIO_CODEC_NONE) {
+ wfd_sink_debug("Skip unprepare audio pipeline for none audio codec.");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
+
+ wfd_sink_error("No-error:unprepare audio sink bin");
+ PRINT_WFD_REF_COUNT(wfd_sink);
+
+ if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+ a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+
+ if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(a_sinkbin)))) {
+ sinkpad = gst_element_get_static_pad(a_sinkbin, "sink");
+ if (!sinkpad) {
+ wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(a_sinkbin));
+ goto ERROR;
+ }
+
+ if (gst_pad_is_linked(sinkpad)) {
+ srcpad = gst_pad_get_peer(sinkpad);
+ if (!srcpad) {
+ wfd_sink_error("failed to get peer pad of %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+
+ wfd_sink_error("try to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (!gst_pad_unlink(srcpad, sinkpad)) {
+ wfd_sink_error("failed to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ } else {
+ wfd_sink_debug("audio sinkbin's sinkpad is not linked, no need to unlink it");
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+
+ wfd_sink_error("try to remove %s from %s", GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+
+ gst_object_ref(a_sinkbin);
+ if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(a_sinkbin))) {
+ wfd_sink_error("failed to remove %s from %s",
+ GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+ goto ERROR;
+ }
+
+ gst_object_unref(pipeline);
+ pipeline = NULL;
+ }
+
+ ret = __mm_wfd_sink_destroy_audio_sinkbin(wfd_sink);
+ if (ret != MM_ERROR_NONE) {
+ wfd_sink_error("failed to destroy audio sinkbin");
+ goto ERROR;
+ }
+ }
+ PRINT_WFD_REF_COUNT(wfd_sink);
+
+ wfd_sink_error("No-error:unprepare audio decode bin");
+ if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
+ a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+
+ if ((pipeline = GST_ELEMENT_CAST(gst_element_get_parent(a_decodebin)))) {
+ sinkpad = gst_element_get_static_pad(a_decodebin, "sink");
+ if (!sinkpad) {
+ wfd_sink_error("failed to get sink pad from %s", GST_ELEMENT_NAME(a_decodebin));
+ goto ERROR;
+ }
+
+ if (gst_pad_is_linked(sinkpad)) {
+ srcpad = gst_pad_get_peer(sinkpad);
+ if (!srcpad) {
+ wfd_sink_error("failed to get peer pad of %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+
+ wfd_sink_error("try to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (!gst_pad_unlink(srcpad, sinkpad)) {
+ wfd_sink_error("failed to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ } else {
+ wfd_sink_debug("audio decodebin's sinkpad is not linked, no need to unlink it");
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+
+ srcpad = gst_element_get_static_pad(a_decodebin, "src");
+ if (!srcpad) {
+ wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(a_decodebin));
+ goto ERROR;
+ }
+
+ if (gst_pad_is_linked(srcpad)) {
+ sinkpad = gst_pad_get_peer(srcpad);
+ if (!sinkpad) {
+ wfd_sink_error("failed to get peer pad of %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ wfd_sink_error("try to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (!gst_pad_unlink(srcpad, sinkpad)) {
+ wfd_sink_error("failed to unlink %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ } else {
+ wfd_sink_debug("audio decodebin's srcpad is not linked, no need to unlink it");
+ }
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+
+ wfd_sink_error("try to remove %s from %s",
+ GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
+ gst_object_ref(a_decodebin);
+ if (!gst_bin_remove(GST_BIN(pipeline), GST_ELEMENT(a_decodebin))) {
+ wfd_sink_error("failed to remove %s from %s",
+ GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
+ goto ERROR;
+ }
+
+ gst_object_unref(pipeline);
+ pipeline = NULL;
+ }
+
+ ret = __mm_wfd_sink_destroy_audio_decodebin(wfd_sink);
+ if (ret != MM_ERROR_NONE) {
+ wfd_sink_error("failed to destroy audio decodebin");
+ goto ERROR;
+ }
+ }
+ PRINT_WFD_REF_COUNT(wfd_sink);
+
+ wfd_sink_debug_fleave();
+
+ return ret;
+
+ /* ERRORS */
+ERROR:
+ if (pipeline) {
+ gst_object_unref(pipeline);
+ pipeline = NULL;
+ }
+ if (sinkpad) {
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ }
+
+ if (srcpad) {
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+
/* need to notify to app */
MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(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)
+int
+__mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **pad)
{
- GstElement *bin = NULL;
+ GstElement *pipeline = NULL;
+ GstElement *a_decodebin = NULL;
+ GstElement *a_sinkbin = NULL;
+ GstPad *srcpad = NULL;
+ GstPad *sinkpad = NULL;
wfd_sink_debug_fenter();
wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->stream_info.audio_stream_info.codec == MM_WFD_SINK_AUDIO_CODEC_NONE) {
+ wfd_sink_debug("Skip prepare audio pipeline for none audio codec");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
/* check audio decodebin is linked */
if (!wfd_sink->audio_decodebin_is_linked) {
}
}
- /* set audio decodebin state as READY */
+ /* add audio decodebin to pipeline */
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");
+ a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+
+ pipeline = GST_ELEMENT_CAST(gst_element_get_parent(a_decodebin));
+ if (!pipeline) {
+ pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+ if (GST_STATE(a_decodebin) <= GST_STATE_NULL) {
+ wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(a_decodebin));
+ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(a_decodebin, GST_STATE_READY)) {
+ wfd_sink_error("failed to set state(READY) to audio decodebin");
+ goto ERROR;
+ }
+ }
+
+ wfd_sink_debug("try to add %s to %s",
+ GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
+ if (!gst_bin_add(GST_BIN(pipeline), GST_ELEMENT(a_decodebin))) {
+ wfd_sink_error("failed to add %s to %s",
+ GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
goto ERROR;
}
+
+ wfd_sink_debug("need to sync state %s with its parent", GST_ELEMENT_NAME(a_decodebin));
+ if (!gst_element_sync_state_with_parent(GST_ELEMENT(a_decodebin))) {
+ wfd_sink_error("failed to sync %s state with parent", GST_ELEMENT_NAME(a_decodebin));
+ goto ERROR;
+ }
+ } else {
+ wfd_sink_debug("%s is already added to %s",
+ GST_ELEMENT_NAME(a_decodebin), GST_ELEMENT_NAME(pipeline));
+ gst_object_unref(pipeline);
+ pipeline = NULL;
}
} else {
wfd_sink_warning("going on without audio decodebin....");
}
- /* set audio sinkbin state as READY */
+ /* add audio sinkbin to pipeline */
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");
+ a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+
+ pipeline = GST_ELEMENT_CAST(gst_element_get_parent(a_sinkbin));
+ if (!pipeline) {
+ pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
+ /* prepare audio sinkbin before adding */
+ if (GST_STATE(a_sinkbin) <= GST_STATE_NULL) {
+ wfd_sink_debug("need to prepare %s", GST_ELEMENT_NAME(a_sinkbin));
+ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(a_sinkbin, GST_STATE_READY)) {
+ wfd_sink_error("failed to set state(READY) to audio sinkbin");
+ goto ERROR;
+ }
+ }
+
+ /* add audio sinkbin to pipeline */
+ wfd_sink_debug("try to add %s to %s",
+ GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+ if (!gst_bin_add(GST_BIN(pipeline), GST_ELEMENT(a_sinkbin))) {
+ wfd_sink_error("failed to add %s to %s",
+ GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+ goto ERROR;
+ }
+
+ /* sync state with parent */
+ wfd_sink_debug("need to sync state %s with its parent", GST_ELEMENT_NAME(a_sinkbin));
+ if (!gst_element_sync_state_with_parent(GST_ELEMENT(a_sinkbin))) {
+ wfd_sink_error("failed to sync %s state with parent", GST_ELEMENT_NAME(a_sinkbin));
goto ERROR;
}
+ } else {
+ wfd_sink_debug("%s is already added to %s",
+ GST_ELEMENT_NAME(a_sinkbin), GST_ELEMENT_NAME(pipeline));
+ gst_object_unref(pipeline);
+ pipeline = NULL;
}
} else {
wfd_sink_warning("going on without audio sinkbin....");
}
+
+ /* link audio decodebin and sinkbin */
+ if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
+ a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
+
+ if (pad)
+ *pad = gst_element_get_static_pad(a_decodebin, "sink");
+
+ if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+
+ a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+
+ srcpad = gst_element_get_static_pad(a_decodebin, "src");
+ if (!srcpad) {
+ wfd_sink_error("faied to get srcpad from %s", GST_ELEMENT_NAME(a_decodebin));
+ goto ERROR;
+ }
+
+ if (!gst_pad_is_linked(srcpad)) {
+ sinkpad = gst_element_get_static_pad(a_sinkbin, "sink");
+ if (!sinkpad) {
+ wfd_sink_error("faied to get sinkpad from %s", GST_ELEMENT_NAME(a_sinkbin));
+ goto ERROR;
+ }
+
+ wfd_sink_debug("try to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+ wfd_sink_error("failed to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+
+ goto ERROR;
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ }
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+ } else if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+ a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
+ if (pad)
+ *pad = gst_element_get_static_pad(a_sinkbin, "sink");
+ }
+
wfd_sink_debug_fleave();
return MM_ERROR_NONE;
/* ERRORS */
ERROR:
+ if (pipeline) {
+ gst_object_unref(pipeline);
+ pipeline = NULL;
+ }
+
+ if (sinkpad) {
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ }
+
+ if (srcpad) {
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+
/* need to notify to app */
MMWFDSINK_POST_MESSAGE(wfd_sink,
- MM_ERROR_WFD_INTERNAL,
- MMWFDSINK_CURRENT_STATE(wfd_sink));
+ MM_ERROR_WFD_INTERNAL,
+ MMWFDSINK_CURRENT_STATE(wfd_sink));
return MM_ERROR_WFD_INTERNAL;
}
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);
+ 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");
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));
+ " 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;
}
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)));
+ 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", */
+ /*wfd_sink_debug ("%s :diff time : %" GST_TIME_FORMAT "", */
/* GST_STR_NULL((GST_OBJECT_NAME(pad))), */
/* GST_TIME_ARGS(diff)); */
}
video_minus_compensation = FALSE;
}
} else {
- wfd_sink_debug("first update video average gap(%lld) ", video_avgrage_gap);
+ wfd_sink_debug("first update video average gap(%"G_GINT64_FORMAT"d) ", 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)));
+ " ~ %" GST_TIME_FORMAT"",
+ GST_TIME_ARGS(wfd_sink->last_buffer_timestamp),
+ GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
}
/* check audio */
audio_minus_compensation = FALSE;
}
} else {
- wfd_sink_debug("first update audio average gap(%lld) ", audio_avgrage_gap);
+ wfd_sink_debug("first update audio average gap(%"G_GINT64_FORMAT"d) ", 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)));
+ " ~ %" 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 */
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);
+ wfd_sink_debug("average diff gap difference beween audio:%s%"G_GINT64_FORMAT"d and video:%s%"G_GINT64_FORMAT"d ",
+ 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 */
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));
+ wfd_sink_debug("do timestamp compensation : %s%"G_GINT64_FORMAT"d (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));
+ wfd_sink_debug("don't need to do timestamp compensation : %s%"G_GINT64_FORMAT"d (ts-offset : %"GST_TIME_FORMAT ")",
+ minus_compensation ? "-" : "", avgrage_gap_diff, GST_TIME_ARGS(ts_offset));
}
/* reset values*/
}
} else {
wfd_sink_debug("first update last buffer timestamp :%" GST_TIME_FORMAT,
- GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+ GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
wfd_sink->last_buffer_timestamp = GST_BUFFER_TIMESTAMP(buffer);
}
static void
-__mm_wfd_sink_demux_pad_added(GstElement *ele, GstPad *pad, gpointer data)
+__mm_wfd_sink_demux_pad_added(GstElement *demux, GstPad *pad, gpointer data)
{
mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
- gchar *name = gst_pad_get_name(pad);
+ gchar *name = NULL;
GstElement *pipeline = NULL;
- GstElement *decodebin = NULL;
- GstElement *sinkbin = NULL;
+ GstElement *valve = 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...");
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
- 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);
+ name = gst_pad_get_name(pad);
+ if (name == NULL) {
+ wfd_sink_error("fail to get pad");
+ goto ERROR;
+ }
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink)) {
- wfd_sink_error("failed to prepare video pipeline....");
- goto ERROR;
- }
+ wfd_sink_debug("Mux pad added, video_codec=%d, audio_codec=%d, name[0] = %c",
+ wfd_sink->stream_info.video_stream_info.codec,
+ wfd_sink->stream_info.audio_stream_info.codec,
+ name[0]);
- 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...");
+ //In case of none vieo codec, we don't add video pad
+ if (wfd_sink->stream_info.video_stream_info.codec == MM_WFD_SINK_VIDEO_CODEC_NONE && name[0] == 'v') {
+ wfd_sink_error("Skip video pad add for none video codec");
+ // Do nothing
+ goto done;
+ }
- MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL, NULL);
+ //In case of none audio codec, we don't add audio pad
+ if (wfd_sink->stream_info.audio_stream_info.codec == MM_WFD_SINK_AUDIO_CODEC_NONE && name[0] == 'a') {
+ wfd_sink_error("Skip audio pad add for none audio codec");
+ // Do nothing
+ goto done;
+ }
- gst_pad_add_probe(pad,
- GST_PAD_PROBE_TYPE_BUFFER,
- _mm_wfd_sink_check_running_time,
- (gpointer)wfd_sink,
- NULL);
+ pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink)) {
- wfd_sink_error("failed to prepare audio pipeline....");
- goto ERROR;
- }
+ /* take srcpad from demuxer added pad */
+ srcpad = gst_object_ref(pad);
- 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;
+ if (name[0] == 'v') {
+ if (wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst)
+ valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst;
+ } else if (name[0] == 'a') {
+ if (wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst)
+ valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst;
}
- srcpad = gst_object_ref(pad);
+ /* add, link and run the valve */
+ if (valve) {
+ wfd_sink_debug("try to add %s to pipeline", GST_ELEMENT_NAME(valve));
- /* add decodebin and link */
- if (decodebin) {
- if (!gst_bin_add(GST_BIN(pipeline), decodebin)) {
+ if (!gst_bin_add(GST_BIN(pipeline), valve)) {
wfd_sink_error("failed to add %s to pipeline",
- GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+ GST_ELEMENT_NAME(valve));
goto ERROR;
}
- sinkpad = gst_element_get_static_pad(decodebin, "sink");
+ sinkpad = gst_element_get_static_pad(valve, "sink");
if (!sinkpad) {
- wfd_sink_error("failed to get sink pad from %s",
- GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+ wfd_sink_error("failed to get sink pad from %s",
+ GST_ELEMENT_NAME(valve));
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)));
+ wfd_sink_debug("try to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+ wfd_sink_error("failed to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
goto ERROR;
}
gst_object_unref(GST_OBJECT(srcpad));
gst_object_unref(GST_OBJECT(sinkpad));
sinkpad = NULL;
- srcpad = gst_element_get_static_pad(decodebin, "src");
+ wfd_sink_debug("try to sync %s's state with parent", GST_ELEMENT_NAME(valve));
+ if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(valve))) {
+ wfd_sink_error("failed to sync %s state with parent",
+ GST_PAD_NAME(valve));
+ goto ERROR;
+ }
+
+ srcpad = gst_element_get_static_pad(valve, "src");
if (!srcpad) {
wfd_sink_error("failed to get src pad from %s",
- GST_STR_NULL(GST_ELEMENT_NAME(decodebin)));
+ GST_ELEMENT_NAME(valve));
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;
- }
+ /* take decodebin/sinkbin */
+ if (name[0] == 'v') {
+ wfd_sink_debug("=========== >>>>>>>>>> Received VIDEO pad...");
- 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;
- }
+ 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 (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)));
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &sinkpad)) {
+ wfd_sink_error("failed to prepare video pipeline....");
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;
- }
+ } else if (name[0] == 'a') {
+ wfd_sink_debug("=========== >>>>>>>>>> Received AUDIO pad...");
+ MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL, NULL);
- /* 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)));
+ 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, &sinkpad)) {
+ wfd_sink_error("failed to prepare audio pipeline....");
goto ERROR;
}
+ } else {
+ wfd_sink_error("unexceptable pad is added!!!");
+ 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;
- }
+ /* link */
+ wfd_sink_debug("try to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+ wfd_sink_error("failed to link %s:%s and %s:%s",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ goto ERROR;
}
- if (name[0] == 'v') {
+ if (name[0] == 'v')
MMWFDSINK_GENERATE_DOT_IF_ENABLED(wfd_sink, "video-pad-added-pipeline");
- } else if (name[0] == 'a') {
+ else if (name[0] == 'a')
MMWFDSINK_GENERATE_DOT_IF_ENABLED(wfd_sink, "audio-pad-added-pipeline");
- }
+done:
MMWFDSINK_FREEIF(name);
+ if (srcpad) {
+ gst_object_unref(GST_OBJECT(srcpad));
+ srcpad = NULL;
+ }
+ if (sinkpad) {
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+ }
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;
+ goto done;
}
static void
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"));
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_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_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);
+ wfd_sink_debug("audio_format : %s \n \t rate : %d \n \t channels : %d \n \t bitwidth : %d \n \t \n",
+ audio_format,
+ stream_info->audio_stream_info.sample_rate,
+ stream_info->audio_stream_info.channels,
+ stream_info->audio_stream_info.bitwidth);
}
- }
+ g_free(audio_format);
+ }
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")) {
+ if (g_strrstr(video_format, "H264")) {
+ stream_info->video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_H264;
+ } else if (g_strrstr(video_format, "H265")) {
+ stream_info->video_stream_info.codec = MM_WFD_SINK_VIDEO_CODEC_H265;
+ } else {
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"))
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_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);
+ video_format,
+ stream_info->video_stream_info.width,
+ stream_info->video_stream_info.height,
+ stream_info->video_stream_info.frame_rate);
}
+
+ g_free(video_format);
}
WFD_SINK_MANAGER_SIGNAL_CMD(wfd_sink);
wfd_sink_debug_fleave();
}
+static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint64 *CEA_resolution,
+ guint64 *VESA_resolution, guint64 *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;
+}
+
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;
+ GstStructure *wfd_audio_codecs = NULL;
+ GstStructure *wfd_video_formats = NULL;
+ GstStructure *wfd_content_protection = NULL;
+ GstStructure *wfd2_video_formats = NULL;
+ GstStructure *wfd2_audio_codecs = NULL;
+ GstStructure *wfd_coupled_sink= NULL;
gint hdcp_version = 0;
gint hdcp_port = 0;
- guint CEA_resolution = 0;
- guint VESA_resolution = 0;
- guint HH_resolution = 0;
+ guint64 CEA_resolution = 0;
+ guint64 VESA_resolution = 0;
+ guint64 HH_resolution = 0;
GObjectClass *klass;
wfd_sink_debug_fenter();
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, "enable-pad-probe")) /* for common wfdsrc */
+ g_object_set(G_OBJECT(wfdsrc), "enable-pad-probe", wfd_sink->ini.trace_buffers_of_wfdsrc, NULL);
+ g_object_set(G_OBJECT(wfdsrc), "udp-buffer-size", 2097152, NULL);
+ g_object_set(G_OBJECT(wfdsrc), "latency", wfd_sink->ini.jitter_buffer_latency, NULL);
+ g_object_set(G_OBJECT(wfdsrc), "user-agent", wfd_sink->ini.user_agent, NULL);
+ g_object_set(G_OBJECT(wfdsrc), "dump-rtsp-message", wfd_sink->ini.dump_rtsp_message, NULL);
+ if (g_object_class_find_property(klass, "dump-rtp-data"))
+ g_object_set(G_OBJECT(wfdsrc), "dump-rtp-data", wfd_sink->ini.dump_rtp_data, NULL);
+ if (g_object_class_find_property(klass, "trace-first-buffer"))
+ g_object_set(G_OBJECT(wfdsrc), "trace-first-buffer", wfd_sink->ini.trace_first_buffer, NULL);
+ if (g_object_class_find_property(klass, "trace-buffers"))
+ g_object_set(G_OBJECT(wfdsrc), "trace-buffers", wfd_sink->ini.trace_buffers, 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);
+ /* set audio parameter for Wi-Fi Display session negotiation */
+ wfd_audio_codecs = gst_structure_new("wfd_audio_codecs",
+ "audio_codec", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_codec,
+ "audio_latency", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_latency,
+ "audio_channels", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_channel,
+ "audio_sampling_frequency", G_TYPE_UINT, wfd_sink->ini.wfd_audio_codecs.audio_sampling_frequency,
+ NULL);
+
+ if (wfd_audio_codecs) {
+ g_object_set(G_OBJECT(wfdsrc), "wfd-audio-codecs", wfd_audio_codecs, NULL);
+ gst_structure_free(wfd_audio_codecs);
+ wfd_audio_codecs = NULL;
+ }
+
+ /* set video parameter for Wi-Fi Display session negotiation */
+ CEA_resolution = wfd_sink->ini.wfd_video_formats.video_cea_support;
+ VESA_resolution = wfd_sink->ini.wfd_video_formats.video_vesa_support;
+ HH_resolution = wfd_sink->ini.wfd_video_formats.video_hh_support;
+
+ __mm_wfd_sink_prepare_video_resolution(wfd_sink->supportive_resolution,
+ &CEA_resolution, &VESA_resolution, &HH_resolution);
+ wfd_video_formats = gst_structure_new("wfd_video_formats",
+ "video_codec", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_codec,
+ "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_native_resolution,
+ "video_cea_support", G_TYPE_UINT64, CEA_resolution,
+ "video_vesa_support", G_TYPE_UINT64, VESA_resolution,
+ "video_hh_support", G_TYPE_UINT64, HH_resolution,
+ "video_profile", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_profile,
+ "video_level", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_level,
+ "video_latency", G_TYPE_UINT, wfd_sink->ini.wfd_video_formats.video_latency,
+ "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_vertical_resolution,
+ "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_horizontal_resolution,
+ "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_minimum_slicing,
+ "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_slice_enc_param,
+ "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.wfd_video_formats.video_framerate_control_support,
+ NULL);
+
+ if (wfd_video_formats) {
+ g_object_set(G_OBJECT(wfdsrc), "wfd-video-formats", wfd_video_formats, NULL);
+ gst_structure_free(wfd_video_formats);
+ wfd_video_formats = NULL;
+ }
+ /* set coupled sink information for Wi-Fi Display session negotiation */
+ wfd_coupled_sink = gst_structure_new("wfd_coupled_sink",
+ "coupled_sink_status", G_TYPE_INT, wfd_sink->coupled_sink_status,
+ "coupled_sink_address", G_TYPE_STRING, wfd_sink->coupled_sink_address,
+ "is_coupled_sink_supported", G_TYPE_BOOLEAN, wfd_sink->is_coupled_sink_supported,
+ NULL);
+
+ if (wfd_coupled_sink) {
+ g_object_set(G_OBJECT(wfdsrc), "wfd-coupled-sink", wfd_coupled_sink, NULL);
+ gst_structure_free(wfd_coupled_sink);
+ wfd_coupled_sink = NULL;
+ }
+
+ /* set hdcp parameter for Wi-Fi Display session negotiation */
+ if (wfd_sink->ini.wfd_content_protection.enable_hdcp) {
+ 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);
+
+ wfd_content_protection = gst_structure_new("wfd_content_protection",
+ "hdcp_version", G_TYPE_INT, hdcp_version,
+ "hdcp_port_no", G_TYPE_INT, hdcp_port,
+ NULL);
+
+ if (wfd_content_protection) {
+ g_object_set(G_OBJECT(wfdsrc), "wfd-content-protection", wfd_content_protection, NULL);
+ gst_structure_free(wfd_content_protection);
+ wfd_content_protection = NULL;
+ }
+ }
- wfd_sink_debug("set video resolution CEA[%x] VESA[%x] HH[%x]", CEA_resolution, VESA_resolution, HH_resolution);
+ if (g_object_class_find_property(klass, "wfd2-audio-codecs")) {
+ /* set audio parameter for Wi-Fi Display R2 session negotiation */
+ wfd2_audio_codecs = gst_structure_new("wfd2-audio-codecs",
+ "audio_codec", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_codec,
+ "audio_lpcm_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_lpcm_mode,
+ "audio_aac_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_aac_mode,
+ "audio_ac3_mode", G_TYPE_UINT, wfd_sink->ini.wfd2_audio_codecs.audio_ac3_mode,
+ NULL);
- 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);
+ if (wfd2_audio_codecs) {
+ g_object_set(G_OBJECT(wfdsrc), "wfd2-audio-codecs", wfd2_audio_codecs, NULL);
+ gst_structure_free(wfd2_audio_codecs);
+ wfd2_audio_codecs = 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);
+ if (g_object_class_find_property(klass, "wfd2-video-format-h264")) {
+ /* set video parameter for Wi-Fi Display R2 session negotiation */
+ CEA_resolution = wfd_sink->ini.wfd2_video_h264_info.video_cea_support;
+ VESA_resolution = wfd_sink->ini.wfd2_video_h264_info.video_vesa_support;
+ HH_resolution = wfd_sink->ini.wfd2_video_h264_info.video_hh_support;
+
+ if (wfd_sink->ini.wfd2_video_formats.video_codec & WFD_VIDEO_H264) {
+ wfd2_video_formats = gst_structure_new("wfd2-video-format-h264",
+ "video_codec", G_TYPE_UINT, WFD_VIDEO_H264,
+ "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.wfd2_video_formats.video_native_resolution,
+ "video_cea_support", G_TYPE_UINT64, CEA_resolution,
+ "video_vesa_support", G_TYPE_UINT64, VESA_resolution,
+ "video_hh_support", G_TYPE_UINT64, HH_resolution,
+ "video_profile", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h264_info.video_profile,
+ "video_level", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h264_info.video_level,
+ "video_latency", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h264_info.video_latency,
+ "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_vertical_resolution,
+ "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_horizontal_resolution,
+ "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_minimum_slicing,
+ "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_slice_enc_param,
+ "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.wfd2_video_h264_info.video_framerate_control_support,
+ "video_non_transcoding_support", G_TYPE_INT, wfd_sink->ini.wfd2_video_formats.video_non_transcoding_support,
+ NULL);
+
+ if (wfd2_video_formats) {
+ g_object_set(G_OBJECT(wfdsrc), "wfd2-video-format-h264", wfd2_video_formats, NULL);
+ gst_structure_free(wfd2_video_formats);
+ wfd2_video_formats = NULL;
+ }
+ }
+ }
- hdcp_param = gst_structure_new("hdcp_param",
- "hdcp_version", G_TYPE_INT, hdcp_version,
- "hdcp_port_no", G_TYPE_INT, hdcp_port,
- NULL);
+ if (g_object_class_find_property(klass, "wfd2-video-format-h265")) {
+ /* set video parameter for Wi-Fi Display R2 session negotiation */
+ CEA_resolution = wfd_sink->ini.wfd2_video_h265_info.video_cea_support;
+ VESA_resolution = wfd_sink->ini.wfd2_video_h265_info.video_vesa_support;
+ HH_resolution = wfd_sink->ini.wfd2_video_h265_info.video_hh_support;
+
+ if (wfd_sink->ini.wfd2_video_formats.video_codec & WFD_VIDEO_H265) {
+ wfd2_video_formats = gst_structure_new("wfd2-video-format-h265",
+ "video_codec", G_TYPE_UINT, WFD_VIDEO_H265,
+ "video_native_resolution", G_TYPE_UINT, wfd_sink->ini.wfd2_video_formats.video_native_resolution,
+ "video_cea_support", G_TYPE_UINT64, CEA_resolution,
+ "video_vesa_support", G_TYPE_UINT64, VESA_resolution,
+ "video_hh_support", G_TYPE_UINT64, HH_resolution,
+ "video_profile", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h265_info.video_profile,
+ "video_level", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h265_info.video_level,
+ "video_latency", G_TYPE_UINT, wfd_sink->ini.wfd2_video_h265_info.video_latency,
+ "video_vertical_resolution", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_vertical_resolution,
+ "video_horizontal_resolution", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_horizontal_resolution,
+ "video_minimum_slicing", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_minimum_slicing,
+ "video_slice_enc_param", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_slice_enc_param,
+ "video_framerate_control_support", G_TYPE_INT, wfd_sink->ini.wfd2_video_h265_info.video_framerate_control_support,
+ "video_non_transcoding_support", G_TYPE_INT, wfd_sink->ini.wfd2_video_formats.video_non_transcoding_support,
+ 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);
+ if (wfd2_video_formats) {
+ g_object_set(G_OBJECT(wfdsrc), "wfd2-video-format-h265", wfd2_video_formats, NULL);
+ gst_structure_free(wfd2_video_formats);
+ wfd2_video_formats = NULL;
+ }
+ }
+ }
- g_signal_connect(wfdsrc, "update-media-info", G_CALLBACK(__mm_wfd_sink_update_stream_info), wfd_sink);
+ wfd_sink->update_stream_info_sig_id = 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->change_av_format_sig_id = g_signal_connect(wfdsrc, "change-av-format",
+ G_CALLBACK(__mm_wfd_sink_change_av_format), wfd_sink);
wfd_sink_debug_fleave();
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);
+ 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)
+static void __mm_wfd_sink_queue_overrun(GstElement *queue, gpointer u_data)
{
+ guint64 time = 0;
+
wfd_sink_debug_fenter();
- return_if_fail(element);
+ return_if_fail(queue);
+
+ g_object_get(G_OBJECT(queue), "current-level-time", &time, NULL);
- wfd_sink_warning("%s is overrun",
- GST_STR_NULL(GST_ELEMENT_NAME(element)));
+ wfd_sink_warning("%s is overrun(%" GST_TIME_FORMAT")",
+ GST_ELEMENT_NAME(queue), GST_TIME_ARGS(time));
wfd_sink_debug_fleave();
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);
+ g_signal_connect(queue, "overrun",
+ G_CALLBACK(__mm_wfd_sink_queue_overrun), wfd_sink);
wfd_sink_debug_fleave();
}
-static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink)
{
MMWFDSinkGstElement *mainbin = NULL;
GList *element_bucket = NULL;
MMWFDSINK_TS_DATA_DUMP(wfd_sink, mainbin[WFD_SINK_M_DEPAY].gst, "src");
+ /* create queue for ts */
+ MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_QUEUE, "queue", "ts_queue", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_QUEUE].gst, "src");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_QUEUE].gst, "sink");
+ g_object_set(G_OBJECT(mainbin[WFD_SINK_M_QUEUE].gst), "max-size-buffers", 200000, NULL);
+
+ /* create valve for demux */
+ MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_D_VALVE, "valve", "demux_valve", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_D_VALVE].gst, "src");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_D_VALVE].gst, "sink");
+
/* 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");
}
}
+ /* create valve for audio */
+ MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_A_VALVE, "valve", "audio_valve", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_A_VALVE].gst, "src");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_A_VALVE].gst, "sink");
+
+ /* create valve for video */
+ MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_V_VALVE, "valve", "video_valve", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_V_VALVE].gst, "src");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_V_VALVE].gst, "sink");
+
/* 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");
}
/* add bus message callback*/
- gst_bus_add_watch(bus, (GstBusFunc)_mm_wfd_sink_msg_callback, wfd_sink);
+ wfd_sink->msg_callback_id = 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);
+ element_bucket = NULL;
gst_object_unref(GST_OBJECT(bus));
+ bus = NULL;
/* now we have completed mainbin. take it */
wfd_sink->pipeline->mainbin = mainbin;
CREATE_ERROR:
wfd_sink_error("ERROR : releasing pipeline");
- if (element_bucket)
+ if (element_bucket) {
g_list_free(element_bucket);
- element_bucket = NULL;
-
- /* finished */
- if (bus)
- gst_object_unref(GST_OBJECT(bus));
- bus = NULL;
+ element_bucket = NULL;
+ }
/* release element which are not added to bin */
for (i = 1; i < WFD_SINK_M_NUM; i++) { /* NOTE : skip pipeline */
mainbin[i].gst = NULL;
} else {
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
}
}
/* release mainbin with it's childs */
- if (mainbin != NULL && mainbin[WFD_SINK_M_PIPE].gst)
+ if (mainbin != NULL && mainbin[WFD_SINK_M_PIPE].gst) {
gst_object_unref(GST_OBJECT(mainbin[WFD_SINK_M_PIPE].gst));
+ mainbin[WFD_SINK_M_PIPE].gst = NULL;
+ }
MMWFDSINK_FREEIF(mainbin);
GstPad *sinkpad = NULL;
GstPad *srcpad = NULL;
GstPad *ghostpad = NULL;
- GList *first_list = NULL;
- GList *last_list = NULL;
+ GList *list_temp = 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);
+ 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;
}
+ if (wfd_sink->stream_info.audio_stream_info.codec == MM_WFD_SINK_AUDIO_CODEC_NONE) {
+ wfd_sink_debug("Skip link audio decodebin for none audio codec.");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
+
/* take audio decodebin */
a_decodebin = wfd_sink->pipeline->a_decodebin;
/* 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;
+ 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));
+ caps = NULL;
+ }
+ 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...");
+ goto fail_to_link;
+ break;
}
if (element_bucket == NULL) {
}
/* get first element's sinkpad for creating ghostpad */
- first_list = g_list_first(element_bucket);
- if (first_list == NULL) {
+ list_temp = g_list_first(element_bucket);
+ if (list_temp == NULL) {
wfd_sink_error("failed to get first list of the element_bucket");
goto fail_to_link;
}
- first_element = (MMWFDSinkGstElement *)first_list->data;
+ first_element = (MMWFDSinkGstElement *)list_temp->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)));
+ GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
goto fail_to_link;
}
/* get last element's src for creating ghostpad */
- last_list = g_list_last(element_bucket);
- if (last_list == NULL) {
+ list_temp = g_list_last(element_bucket);
+ if (list_temp == NULL) {
wfd_sink_error("failed to get last list of the element_bucket");
goto fail_to_link;
}
- last_element = (MMWFDSinkGstElement *)last_list->data;
+ last_element = (MMWFDSinkGstElement *)list_temp->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)));
+ GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
goto fail_to_link;
}
/* ERRORS*/
fail_to_link:
- if (srcpad)
+ if (srcpad) {
gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
+ srcpad = NULL;
+ }
- if (sinkpad)
+ if (sinkpad) {
gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
+ sinkpad = NULL;
+ }
g_list_free(element_bucket);
return MM_ERROR_NONE;
}
-static int __mm_wfd_sink_destroy_audio_decodebin(mm_wfd_sink_t *wfd_sink)
+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_error_fenter();
wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
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");
+ wfd_sink_error("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");
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_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);
+ wfd_sink_debug("%s has parent.(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));
+ parent = NULL;
}
}
}
/* release audio decodebin with it's childs */
- if (a_decodebin[WFD_SINK_A_D_BIN].gst)
+ if (a_decodebin[WFD_SINK_A_D_BIN].gst) {
gst_object_unref(GST_OBJECT(a_decodebin[WFD_SINK_A_D_BIN].gst));
+ a_decodebin[WFD_SINK_A_D_BIN].gst = NULL;
+ }
} else {
wfd_sink_debug("audio decodebin has parent(%s), unref it ",
- GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+ GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
wfd_sink->audio_decodebin_is_linked = FALSE;
MMWFDSINK_FREEIF(wfd_sink->pipeline->a_decodebin);
- wfd_sink_debug_fleave();
+ wfd_sink_error_fleave();
return MM_ERROR_NONE;
}
-static int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_audio_decodebin(mm_wfd_sink_t *wfd_sink)
{
MMWFDSinkGstElement *a_decodebin = NULL;
gint audio_codec = WFD_AUDIO_UNKNOWN;
wfd_sink_debug_fenter();
wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->pipeline->a_decodebin != NULL) {
+ wfd_sink_error("The audio decode bin is already created.");
+ return MM_ERROR_NONE;
+ }
+
+ if (wfd_sink->stream_info.audio_stream_info.codec == MM_WFD_SINK_AUDIO_CODEC_NONE) {
+ wfd_sink_debug("Skip create audio decodebin for none audio codec.");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
/* 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;
+ 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.wfd_audio_codecs.audio_codec;
+ link = FALSE;
+ break;
}
/* alloc handles */
/* 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");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_QUEUE].gst, "src");
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");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_decodebin[WFD_SINK_A_D_HDCP].gst, "src");
/* create codec */
- audio_codec = wfd_sink->ini.audio_codec;
+ audio_codec = wfd_sink->ini.wfd_audio_codecs.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);
a_decodebin[i].gst = NULL;
} else {
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
}
}
- /* release audioo decodebin with it's childs */
- if (a_decodebin != NULL && a_decodebin[WFD_SINK_A_D_BIN].gst)
+ /* release audio 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));
+ a_decodebin[WFD_SINK_A_D_BIN].gst = NULL;
+ }
MMWFDSINK_FREEIF(a_decodebin);
return MM_ERROR_WFD_INTERNAL;
}
-static int __mm_wfd_sink_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
+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_error_fenter();
wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
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");
+ wfd_sink_error("audio sinkbin 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");
+ wfd_sink_error("try to change state of audio sinkbin 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");
+ wfd_sink_error("failed to change state of audio sinkbin to NULL");
return MM_ERROR_WFD_INTERNAL;
}
}
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_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);
+ wfd_sink_debug("%s has parent.(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));
+ parent = NULL;
}
}
}
- /* release audio decodebin with it's childs */
- if (a_sinkbin[WFD_SINK_A_S_BIN].gst)
+ /* release audio sinkbin 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));
-
+ a_sinkbin[WFD_SINK_A_S_BIN].gst = NULL;
+ }
} else {
wfd_sink_debug("audio sinkbin has parent(%s), unref it ",
- GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+ GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
MMWFDSINK_FREEIF(wfd_sink->pipeline->a_sinkbin);
- wfd_sink_debug_fleave();
+ wfd_sink_error_fleave();
return MM_ERROR_NONE;
}
-static int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_audio_sinkbin(mm_wfd_sink_t *wfd_sink)
{
MMWFDSinkGstElement *a_sinkbin = NULL;
MMWFDSinkGstElement *first_element = NULL;
GstPad *ghostpad = NULL;
GstPad *pad = NULL;
gint i = 0;
- GList *first_list = NULL;
+ GList *list_temp = NULL;
wfd_sink_debug_fenter();
wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->pipeline->a_sinkbin != NULL) {
+ wfd_sink_error("The audio sink bin is already created.");
+ return MM_ERROR_NONE;
+ }
+
+ if (wfd_sink->stream_info.audio_stream_info.codec == MM_WFD_SINK_AUDIO_CODEC_NONE) {
+ wfd_sink_error("Skip create audio sink bin for non audio codec.");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
/* alloc handles */
a_sinkbin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_A_S_NUM);
}
/* create resampler */
- MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_RESAMPLER, wfd_sink->ini.name_of_audio_resampler, "audio_resampler", TRUE);
+ 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_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");
+ MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_QUEUE,
+ wfd_sink->ini.name_of_audio_sinkbin_queue, "audio_sinkbin_queue", TRUE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_QUEUE].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_QUEUE].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_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)) {
}
/* get first element's of the audio sinkbin */
- first_list = g_list_first(element_bucket);
- if (first_list == NULL) {
+ list_temp = g_list_first(element_bucket);
+ if (list_temp == NULL) {
wfd_sink_error("failed to get first list of the element_bucket");
goto CREATE_ERROR;
}
- first_element = (MMWFDSinkGstElement *)first_list->data;
+ first_element = (MMWFDSinkGstElement *)list_temp->data;
if (!first_element) {
wfd_sink_error("failed to get first element of the audio sinkbin");
goto CREATE_ERROR;
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)));
+ GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
goto CREATE_ERROR;
}
goto CREATE_ERROR;
}
gst_object_unref(GST_OBJECT(pad));
+ pad = NULL;
g_list_free(element_bucket);
+ element_bucket = NULL;
/* take it */
wfd_sink->pipeline->a_sinkbin = a_sinkbin;
CREATE_ERROR:
wfd_sink_error("failed to create audio sinkbin, releasing all");
- if (pad)
+ if (pad) {
gst_object_unref(GST_OBJECT(pad));
- pad = NULL;
-
- if (ghostpad)
+ pad = NULL;
+ }
+ if (ghostpad) {
gst_object_unref(GST_OBJECT(ghostpad));
- ghostpad = NULL;
-
- if (element_bucket)
+ ghostpad = NULL;
+ }
+ if (element_bucket) {
g_list_free(element_bucket);
- element_bucket = NULL;
+ element_bucket = NULL;
+ }
/* release element which are not added to bin */
for (i = 1; i < WFD_SINK_A_S_NUM; i++) { /* NOTE : skip bin */
a_sinkbin[i].gst = NULL;
} else {
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
}
}
/* release audio sinkbin with it's childs */
- if (a_sinkbin != NULL && a_sinkbin[WFD_SINK_A_S_BIN].gst)
+ 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));
-
+ a_sinkbin[WFD_SINK_A_S_BIN].gst = NULL;
+ }
MMWFDSINK_FREEIF(a_sinkbin);
return MM_ERROR_WFD_INTERNAL;
MMWFDSinkGstElement *first_element = NULL;
MMWFDSinkGstElement *last_element = NULL;
GList *element_bucket = NULL;
+ GList *list_temp = 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);
+ 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;
}
+ if (wfd_sink->stream_info.video_stream_info.codec == MM_WFD_SINK_VIDEO_CODEC_NONE) {
+ wfd_sink_debug("Skip link video decodebin for none video codec.");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
+
/* take video decodebin */
v_decodebin = wfd_sink->pipeline->v_decodebin;
/* 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;
+ case MM_WFD_SINK_VIDEO_CODEC_H264:
+ if (v_decodebin[WFD_SINK_V_D_H264_PARSE].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H264_PARSE]);
+ if (v_decodebin[WFD_SINK_V_D_H264_DEC].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H264_DEC]);
+ break;
+
+ case MM_WFD_SINK_VIDEO_CODEC_H265:
+ if (v_decodebin[WFD_SINK_V_D_H265_PARSE].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H265_PARSE]);
+ if (v_decodebin[WFD_SINK_V_D_H265_DEC].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_H265_DEC]);
+ break;
+ case MM_WFD_SINK_VIDEO_CODEC_VP9:
+ if (v_decodebin[WFD_SINK_V_D_VP9_PARSE].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_VP9_PARSE]);
+ if (v_decodebin[WFD_SINK_V_D_VP9_DEC].gst)
+ element_bucket = g_list_append(element_bucket, &v_decodebin[WFD_SINK_V_D_VP9_DEC]);
+ break;
+
+ default:
+ wfd_sink_error("video codec is not decied yet. cannot link video decpdebin...");
+ goto fail_to_link;
+ break;
}
if (element_bucket == NULL) {
}
/* get first element's sinkpad for creating ghostpad */
- first_list = g_list_first(element_bucket);
- if (first_list == NULL) {
+ list_temp = g_list_first(element_bucket);
+ if (list_temp == NULL) {
wfd_sink_error("failed to get first list of the element_bucket");
goto fail_to_link;
}
- first_element = (MMWFDSinkGstElement *)first_list->data;
+ first_element = (MMWFDSinkGstElement *)list_temp->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)));
+ GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
goto fail_to_link;
}
/* get last element's src for creating ghostpad */
- last_list = g_list_last(element_bucket);
- if (last_list == NULL) {
+ list_temp = g_list_last(element_bucket);
+ if (list_temp == NULL) {
wfd_sink_error("failed to get last list of the element_bucket");
goto fail_to_link;
}
- last_element = (MMWFDSinkGstElement *)last_list->data;
+ last_element = (MMWFDSinkGstElement *)list_temp->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)));
+ GST_STR_NULL(GST_ELEMENT_NAME(last_element->gst)));
goto fail_to_link;
}
/* ERRORS*/
fail_to_link:
- if (srcpad != NULL)
+ if (srcpad != NULL) {
gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
+ srcpad = NULL;
+ }
- if (sinkpad != NULL)
+ if (sinkpad != NULL) {
gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
-
- g_list_free(element_bucket);
+ sinkpad = NULL;
+ }
+ if (element_bucket != NULL) {
+ g_list_free(element_bucket);
+ element_bucket = NULL;
+ }
return MM_ERROR_WFD_INTERNAL;
}
/* 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);
+ wfd_sink_info("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);
+ wfd_sink_info("check display visible attribute: %d", visible);
+
+ if (FALSE == visible) {
+ wfd_sink_info("skipped to prepare video sink. display_visible is FALSE.");
+ g_object_set(G_OBJECT(video_sink), "visible", visible, NULL);
+ return MM_ERROR_NONE;
+ }
/* 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)");
+ 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 %p", 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;
+ }
+ break;
+ case MM_DISPLAY_SURFACE_OVERLAY:
+ if (USE_EXTERNAL_WL_DISPLAY_HANDLE) {
+ gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink),
+ wfd_sink->display_surface_id);
+ } else {
+ gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(video_sink),
+ wfd_sink->display_surface_id);
+ }
+ break;
+ case MM_DISPLAY_SURFACE_NULL:
+ /* do nothing */
+ wfd_sink_error("Not Supported Surface.");
+ return MM_ERROR_WFD_INTERNAL;
+ default:
+ wfd_sink_error("Not Supported Surface.(default case)");
+ return MM_ERROR_WFD_INTERNAL;
}
g_object_set(G_OBJECT(video_sink), "qos", FALSE, NULL);
return MM_ERROR_NONE;
}
-static int __mm_wfd_sink_destroy_video_decodebin(mm_wfd_sink_t *wfd_sink)
+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_error_fenter();
wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
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");
+ wfd_sink_error("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");
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_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);
+ wfd_sink_debug("%s has parent.(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));
+ parent = NULL;
}
}
}
/* 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);
+ 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);
+
+ gst_object_unref(GST_OBJECT(v_decodebin[WFD_SINK_V_D_BIN].gst));
+ v_decodebin[WFD_SINK_V_D_BIN].gst = NULL;
}
} else {
wfd_sink_debug("video decodebin has parent(%s), unref it",
- GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+ GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
wfd_sink->video_decodebin_is_linked = FALSE;
MMWFDSINK_FREEIF(wfd_sink->pipeline->v_decodebin);
- wfd_sink_debug_fleave();
+ wfd_sink_error_fleave();
return MM_ERROR_NONE;
}
-static int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
{
MMWFDSinkGstElement *v_decodebin = NULL;
guint video_codec = WFD_VIDEO_UNKNOWN;
wfd_sink_debug_fenter();
wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
+ 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 */
+ if (wfd_sink->stream_info.video_stream_info.codec == MM_WFD_SINK_VIDEO_CODEC_NONE) {
+ wfd_sink_debug("Skip create video decodebin for none video codec.");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
+
+ /* check video 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;
+ case MM_WFD_SINK_VIDEO_CODEC_H264:
+ video_codec = WFD_VIDEO_H264;
+ link = TRUE;
+ break;
+ case MM_WFD_SINK_VIDEO_CODEC_H265:
+ video_codec = WFD_VIDEO_H265;
+ link = TRUE;
+ break;
+ case MM_WFD_SINK_VIDEO_CODEC_VP9:
+ video_codec = WFD_VIDEO_VP9;
+ 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.wfd_video_formats.video_codec | wfd_sink->ini.wfd2_video_formats.video_codec;
+ link = FALSE;
+ break;
}
/* alloc handles */
/* 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");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_QUEUE].gst, "src");
if (v_decodebin[WFD_SINK_V_D_QUEUE].gst)
__mm_wfd_sink_prepare_queue(wfd_sink, v_decodebin[WFD_SINK_V_D_QUEUE].gst);
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");
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_H264_PARSE, wfd_sink->ini.name_of_video_h264_parser, "video_h264_parser", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H264_PARSE].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H264_PARSE].gst, "src");
+
+ if (!g_strcmp0(wfd_sink->ini.name_of_video_h264_decoder, "sprddec_h264") ||
+ !g_strcmp0(wfd_sink->ini.name_of_video_h264_decoder, "omxdec_h264")) {
+ /* acquire HW resource */
+ wfd_sink_error("wfd_sink->ini.name_of_video_h264_decoder1 :: %s", wfd_sink->ini.name_of_video_h264_decoder);
+ if (__mm_wfd_sink_acquire_hw_resource(wfd_sink, MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+ wfd_sink_error("failed to acquire video decoder resource");
+ goto CREATE_ERROR;
+ }
+ }
+
+ /* create dec */
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_H264_DEC, wfd_sink->ini.name_of_video_h264_decoder, "video_h264_dec", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H264_DEC].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H264_DEC].gst, "src");
+ if (v_decodebin[WFD_SINK_V_D_H264_DEC].gst) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_videodec(wfd_sink, v_decodebin[WFD_SINK_V_D_H264_DEC].gst)) {
+ wfd_sink_error("failed to set video decoder property...");
+ goto CREATE_ERROR;
+ }
+ }
+ }
+
+ if (video_codec & WFD_VIDEO_H265) {
+ /* create parser */
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_H265_PARSE, wfd_sink->ini.name_of_video_h265_parser, "video_h265_parser", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H265_PARSE].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H265_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_H265_DEC, wfd_sink->ini.name_of_video_h265_decoder, "video_h265_dec", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H265_DEC].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H265_DEC].gst, "src");
+ if (v_decodebin[WFD_SINK_V_D_H265_DEC].gst) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_videodec(wfd_sink, v_decodebin[WFD_SINK_V_D_H265_DEC].gst)) {
+ wfd_sink_error("failed to set video decoder property...");
+ goto CREATE_ERROR;
+ }
+ }
+ }
+ if (video_codec & WFD_VIDEO_VP9) {
+ /* create parser */
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_VP9_PARSE, wfd_sink->ini.name_of_video_vp9_parser, "video_vp9_parser", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_VP9_PARSE].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_VP9_PARSE].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)) {
+ MMWFDSINK_CREATE_ELEMENT(v_decodebin, WFD_SINK_V_D_VP9_DEC, wfd_sink->ini.name_of_video_vp9_decoder, "video_vp9_dec", FALSE);
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_VP9_DEC].gst, "sink");
+ MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_VP9_DEC].gst, "src");
+ if (v_decodebin[WFD_SINK_V_D_VP9_DEC].gst) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_videodec(wfd_sink, v_decodebin[WFD_SINK_V_D_VP9_DEC].gst)) {
wfd_sink_error("failed to set video decoder property...");
goto CREATE_ERROR;
}
v_decodebin[i].gst = NULL;
} else {
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
}
}
/* release video decodebin with it's childs */
- if (v_decodebin != NULL && v_decodebin[WFD_SINK_V_D_BIN].gst)
+ 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));
+ v_decodebin[WFD_SINK_V_D_BIN].gst = NULL;
+ }
MMWFDSINK_FREEIF(v_decodebin);
return MM_ERROR_WFD_INTERNAL;
}
-static int __mm_wfd_sink_destroy_video_sinkbin(mm_wfd_sink_t *wfd_sink)
+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_error_fenter();
wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
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");
+ wfd_sink_error("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");
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_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);
+ wfd_sink_debug("%s has parent.(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));
+ parent = NULL;
}
}
}
/* 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));
+ v_sinkbin[WFD_SINK_V_S_BIN].gst = NULL;
}
} else {
wfd_sink_debug("video sinkbin has parent(%s), unref it ",
- GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
+ GST_STR_NULL(GST_OBJECT_NAME(GST_OBJECT(parent))));
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
MMWFDSINK_FREEIF(wfd_sink->pipeline->v_sinkbin);
- wfd_sink_debug_fleave();
+ wfd_sink_error_fleave();
return MM_ERROR_NONE;
}
-static int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
{
MMWFDSinkGstElement *first_element = NULL;
MMWFDSinkGstElement *v_sinkbin = NULL;
wfd_sink_debug_fenter();
wfd_sink_return_val_if_fail(wfd_sink &&
- wfd_sink->pipeline,
- MM_ERROR_WFD_NOT_INITIALIZED);
+ wfd_sink->pipeline,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ if (wfd_sink->pipeline->v_sinkbin != NULL) {
+ wfd_sink_error("The video sink bin is already created.");
+ return MM_ERROR_NONE;
+ }
+
+ if (wfd_sink->stream_info.video_stream_info.codec == MM_WFD_SINK_VIDEO_CODEC_NONE) {
+ wfd_sink_error("Skip create video sink bin for non video codec.");
+ wfd_sink_debug_fleave();
+ return MM_ERROR_NONE;
+ }
/* alloc handles */
v_sinkbin = (MMWFDSinkGstElement *)g_malloc0(sizeof(MMWFDSinkGstElement) * WFD_SINK_V_S_NUM);
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));
+ caps = NULL;
}
/* create sink */
mm_attrs_get_int_by_name(wfd_sink->attrs, "display_surface_type", &surface_type);
-
- if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
+ if (surface_type == MM_DISPLAY_SURFACE_OVERLAY &&
+ (__mm_wfd_sink_acquire_hw_resource(wfd_sink, MM_WFD_SINK_RESOURCE_TYPE_VIDEO_OVERLAY) == MM_ERROR_NONE)) {
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);
goto CREATE_ERROR;
}
+ wfd_sink->interrupted_by_resource = FALSE;
+
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)) {
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)));
+ GST_STR_NULL(GST_ELEMENT_NAME(first_element->gst)));
goto CREATE_ERROR;
}
}
gst_object_unref(GST_OBJECT(pad));
+ pad = NULL;
g_list_free(element_bucket);
-
+ element_bucket = NULL;
/* take it */
wfd_sink->pipeline->v_sinkbin = v_sinkbin;
CREATE_ERROR:
wfd_sink_error("failed to create video sinkbin, releasing all");
- if (pad)
+ if (pad) {
gst_object_unref(GST_OBJECT(pad));
- pad = NULL;
+ pad = NULL;
+ }
- if (ghostpad)
+ if (ghostpad) {
gst_object_unref(GST_OBJECT(ghostpad));
- ghostpad = NULL;
+ ghostpad = NULL;
+ }
- g_list_free(element_bucket);
+ 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_V_S_NUM; i++) { /* NOTE : skip bin */
v_sinkbin[i].gst = NULL;
} else {
gst_object_unref(GST_OBJECT(parent));
+ parent = NULL;
}
}
}
/* release video sinkbin with it's childs */
- if (v_sinkbin != NULL && v_sinkbin[WFD_SINK_V_S_BIN].gst)
+ 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));
-
+ v_sinkbin[WFD_SINK_V_S_BIN].gst = NULL;
+ }
MMWFDSINK_FREEIF(v_sinkbin);
return MM_ERROR_WFD_INTERNAL;
}
-static int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
+int __mm_wfd_sink_destroy_pipeline(mm_wfd_sink_t *wfd_sink)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstBus *bus = NULL;
wfd_sink_debug_fenter();
MMWFDSinkGstElement *mainbin = wfd_sink->pipeline->mainbin;
if (mainbin) {
+
+ PRINT_WFD_REF_COUNT(wfd_sink);
+
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");
+ wfd_sink_error("failed to change state of pipeline to NULL. ret[%d]", ret);
return MM_ERROR_WFD_INTERNAL;
+ } else {
+ wfd_sink_debug("Successed to change state of pipeline to NULL");
+ }
+
+ bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[WFD_SINK_M_PIPE].gst));
+ if (bus) {
+ GstMessage *gst_msg = NULL;
+ while ((gst_msg = gst_bus_pop(bus)) != NULL) {
+ _mm_wfd_sink_msg_callback(bus, gst_msg, (gpointer)wfd_sink);
+ gst_message_unref(gst_msg);
+ gst_msg = NULL;
+ }
+ gst_object_unref(bus);
+ bus = NULL;
}
+ PRINT_WFD_REF_COUNT(wfd_sink);
+
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;
}
gst_object_unref(GST_OBJECT(mainbin[WFD_SINK_M_PIPE].gst));
+ mainbin[WFD_SINK_M_PIPE].gst = NULL;
MMWFDSINK_FREEIF(mainbin);
}
MMWFDSINK_FREEIF(wfd_sink->pipeline);
}
+ if (wfd_sink->msg_callback_id > 0) {
+ g_source_remove(wfd_sink->msg_callback_id);
+ wfd_sink->msg_callback_id = 0;
+ }
+
wfd_sink->audio_decodebin_is_linked = FALSE;
wfd_sink->video_decodebin_is_linked = FALSE;
wfd_sink->need_to_reset_basetime = FALSE;
+ wfd_sink->supportive_resolution = MM_WFD_SINK_RESOLUTION_UNKNOWN;
wfd_sink_debug_fleave();
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->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;
+ 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);
+ item = NULL;
+ 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;
}
}
}
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));
+ 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)
return;
}
-const gchar * _mm_wfds_sink_get_state_name(MMWFDSinkStateType state)
+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";
+ 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;
return MM_ERROR_NONE;
}
+
+int _mm_wfd_sink_set_display_overlay(mm_wfd_sink_t *wfd_sink, void *display_object)
+{
+ int wl_surface_id = 0;
+ static void *display_overlay = NULL;
+ int wl_window_x = 0;
+ int wl_window_y = 0;
+ int wl_window_width = 0;
+ int wl_window_height = 0;
+ struct wl_surface *wl_surface = NULL;
+ struct wl_display *wl_display = NULL;
+ Ecore_Wl2_Window *wl2_window = NULL;
+ Ecore_Wl2_Display *wl2_display = NULL;
+ wl_client *wlclient = NULL;
+ Evas_Object *obj = NULL;
+ void *object = display_object;
+ const char *object_type = NULL;
+ int ret = 0;
+ pid_t pid = getpid();
+ pid_t tid = syscall(SYS_gettid);
+
+ if (pid != tid) {
+ wfd_sink_error("API isn't called in main thread");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ if (object == NULL) {
+ wfd_sink_debug("display object is NULL!");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ obj = (Evas_Object *)object;
+ object_type = evas_object_type_get(obj);
+ wfd_sink_debug("window object type : %s", object_type);
+
+ if (strcmp(object_type, "elm_win")) {
+ wfd_sink_error("Window type is not elm_win");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+
+ /* wayland overlay surface */
+ wfd_sink_info("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);
+
+ wl2_window = ecore_evas_wayland2_window_get(ecore_evas_ecore_evas_get(evas_object_evas_get(obj)));
+ ecore_wl2_window_video_has(wl2_window, EINA_TRUE);
+ wl_surface = ecore_wl2_window_surface_get(wl2_window);
+
+ /* get wl_display */
+ wl2_display = ecore_wl2_connected_display_get(NULL);
+ wl_display = ecore_wl2_display_get(wl2_display);
+
+ wfd_sink_debug("previous display object : %p current object : %p", display_overlay, object);
+ if (wl_surface && wl_display && (wl_surface_id == 0 || display_overlay != object)) {
+ wfd_sink_debug("surface = %p, wl_display = %p", wl_surface, wl_display);
+ display_overlay = object;
+
+ ret = mm_wfd_sink_wlclient_create(&wlclient);
+ if (ret != MM_ERROR_NONE) {
+ wfd_sink_error("Wayland client create failure");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ wfd_sink_debug("Try to get surface id");
+
+ 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 (wl_surface_id == 0) {
+ wfd_sink_error("wl_surface_id cannot be zero.");
+ return MM_ERROR_WFD_INTERNAL;
+ }
+ wfd_sink->display_surface_id = wl_surface_id;
+
+ if (wlclient) {
+ g_free(wlclient);
+ wlclient = NULL;
+ }
+ }
+ return MM_ERROR_NONE;
+}
+
+void __mm_wfd_sink_print_ref_count(mm_wfd_sink_t *wfd_sink)
+{
+ int i = 0;
+ MMWFDSinkGstElement *mainbin = NULL;
+ MMWFDSinkGstElement *v_decodebin = NULL;
+ MMWFDSinkGstElement *a_decodebin = NULL;
+ MMWFDSinkGstElement *v_sinkbin = NULL;
+ MMWFDSinkGstElement *a_sinkbin = NULL;
+
+ wfd_sink_debug_fenter();
+
+ wfd_sink_return_if_fail(wfd_sink);
+ wfd_sink_return_if_fail(wfd_sink->pipeline);
+
+ wfd_sink_debug("************* wfd pipeline ref count start *************");
+ wfd_sink_debug("try to check mainbin");
+
+ if (wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst) {
+ mainbin = wfd_sink->pipeline->mainbin;
+
+ for (i = 0; i < WFD_SINK_M_NUM; i++) {
+ if (mainbin[i].gst) {
+ wfd_sink_debug("%s(current ref %d)",
+ GST_ELEMENT_NAME(mainbin[i].gst),
+ GST_OBJECT_REFCOUNT(mainbin[i].gst));
+ }
+ }
+ }
+
+ wfd_sink_debug("try to check a_decodebin");
+
+ if (wfd_sink->pipeline->a_decodebin &&
+ wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst) {
+ a_decodebin = wfd_sink->pipeline->a_decodebin;
+
+ for (i = 0; i < WFD_SINK_A_D_NUM; i++) {
+ if (a_decodebin[i].gst) {
+ wfd_sink_debug("%s(current ref %d)",
+ GST_ELEMENT_NAME(a_decodebin[i].gst),
+ GST_OBJECT_REFCOUNT(a_decodebin[i].gst));
+ }
+ }
+ }
+
+ wfd_sink_debug("try to check a_sinkbin");
+
+ if (wfd_sink->pipeline->a_sinkbin &&
+ wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst) {
+ a_sinkbin = wfd_sink->pipeline->a_sinkbin;
+
+ for (i = 0; i < WFD_SINK_A_S_NUM; i++) {
+ if (a_sinkbin[i].gst) {
+ wfd_sink_debug("%s(current ref %d)",
+ GST_ELEMENT_NAME(a_sinkbin[i].gst),
+ GST_OBJECT_REFCOUNT(a_sinkbin[i].gst));
+ }
+ }
+ }
+
+ wfd_sink_debug("try to check v_decodebin");
+
+ if (wfd_sink->pipeline->v_decodebin &&
+ wfd_sink->pipeline->v_decodebin[WFD_SINK_V_D_BIN].gst) {
+ v_decodebin = wfd_sink->pipeline->v_decodebin;
+
+ for (i = 0; i < WFD_SINK_V_D_NUM; i++) {
+ if (v_decodebin[i].gst) {
+ wfd_sink_debug("%s(current ref %d)",
+ GST_ELEMENT_NAME(v_decodebin[i].gst),
+ GST_OBJECT_REFCOUNT(v_decodebin[i].gst));
+ }
+ }
+ }
+
+ wfd_sink_debug("try to check v_sinkbin");
+
+ if (wfd_sink->pipeline->v_sinkbin &&
+ wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
+ v_sinkbin = wfd_sink->pipeline->v_sinkbin;
+
+ for (i = 0; i < WFD_SINK_V_S_NUM; i++) {
+ if (v_sinkbin[i].gst) {
+ wfd_sink_debug("%s(current ref %d)",
+ GST_ELEMENT_NAME(v_sinkbin[i].gst),
+ GST_OBJECT_REFCOUNT(v_sinkbin[i].gst));
+ }
+ }
+ }
+ wfd_sink_debug("************* wfd pipeline ref count end *************");
+ wfd_sink_debug_fleave();
+}