#include "mm_wfd_sink_enum.h"
#include "mm_wfd_sink_wayland.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_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_destroy_audio_sinkbin(mm_wfd_sink_t *wfd_sink);
+static int __mm_wfd_sink_destroy_video_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);
+static gboolean _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data);
/* state */
static int __mm_wfd_sink_set_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkStateType state);
wfd_sink_debug_fenter();
wfd_sink_return_val_if_fail(uri && strlen(uri) > strlen("rtsp://"),
- MM_ERROR_WFD_INVALID_ARGUMENT);
+ 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);
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);
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);
/* initializing gstreamer */
if (!gst_init_check(argc, &argv, &err)) {
wfd_sink_error("failed to initialize gstreamer: %s",
- err ? err->message : "unknown error occurred");
+ err ? err->message : "unknown error occurred");
if (err)
g_error_free(err);
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));
+ 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 to %s:%s",
+ 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 is already linked",
+ GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+ 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)
{
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)));
+ 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)));
+ 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))));
+ (GST_STR_NULL(GST_OBJECT_NAME(clock))));
}
wfd_sink->clock = clock;
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++;
}
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;
}
}
/* 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);
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);
+ MM_ERROR_WFD_INVALID_ARGUMENT);
wfd_sink_debug("try to set %s state ", gst_element_state_get_name(state));
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);
+ &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_unprepare_video_pipeline(mm_wfd_sink_t *wfd_sink)
+{
+ 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,
+ MM_ERROR_WFD_NOT_INITIALIZED);
+
+ 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_debug("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;
+
+ 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_debug("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_debug("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);
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst,
+ MM_ERROR_WFD_NOT_INITIALIZED);
/* check video decodebin is linked */
if (!wfd_sink->video_decodebin_is_linked) {
wfd_sink_error("failed to link video decodebin.....");
goto ERROR;
}
- }
+ }
+
+ /* check video sinkbin is created */
+ if (wfd_sink->pipeline->v_sinkbin == NULL) {
+ if (MM_ERROR_NONE != __mm_wfd_sink_create_video_sinkbin(wfd_sink)) {
+ wfd_sink_error("failed to create video sinkbin....");
+ goto ERROR;
+ }
+ }
+ /* add video decodebin to pipeline */
+ 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;
+
+ 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....");
+ }
+
+ /* add video sinkbin to pipeline */
+ 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;
+
+ 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);
+
+ 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_debug("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;
+
+ 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;
+ }
- /* check video sinkbin is created */
- if (wfd_sink->pipeline->v_sinkbin == NULL) {
- if (MM_ERROR_NONE != __mm_wfd_sink_create_video_sinkbin(wfd_sink)) {
- wfd_sink_error("failed to create video sinkbin....");
+ 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);
- /* set video decodebin state as READY */
- 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 (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");
+ 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;
}
- }
- } else {
- wfd_sink_warning("going on without video decodebin....");
- }
- /* set video sinkbin state as READY */
- if (wfd_sink->pipeline->v_sinkbin && wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst) {
- v_sinkbin = wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst;
- 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");
+ 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_debug("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_debug("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;
}
- } else {
- wfd_sink_warning("going on without video sinkbin....");
}
+ PRINT_WFD_REF_COUNT(wfd_sink);
wfd_sink_debug_fleave();
- return MM_ERROR_NONE;
+ 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, GstPad **pad)
{
+ 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);
/* 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) {
a_decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].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");
+
+ 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) {
a_sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
- 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");
+
+ 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 "", */
}
} 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 */
}
} 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 */
}
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);
+ 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 */
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));
+ 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);
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));
+ 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);
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);
+ wfd_sink->pipeline &&
+ wfd_sink->pipeline->mainbin &&
+ wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
- /* take decodebin/sinkbin */
- if (name[0] == 'v') {
- wfd_sink_debug("=========== >>>>>>>>>> Received VIDEO pad...");
-
- MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL, NULL);
-
- gst_pad_add_probe(pad,
- GST_PAD_PROBE_TYPE_BUFFER,
- _mm_wfd_sink_check_running_time,
- (gpointer)wfd_sink,
- NULL);
-
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &sinkpad)) {
- wfd_sink_error("failed to prepare video pipeline....");
- goto ERROR;
- }
+ /* take srcpad from demuxer added pad */
+ srcpad = gst_object_ref(pad);
- 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;
+ 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') {
- wfd_sink_debug("=========== >>>>>>>>>> Received AUDIO pad...");
-
- MMWFDSINK_PAD_PROBE(wfd_sink, pad, NULL, NULL);
-
- gst_pad_add_probe(pad,
- GST_PAD_PROBE_TYPE_BUFFER,
- _mm_wfd_sink_check_running_time,
- (gpointer)wfd_sink,
- NULL);
-
- if (MM_ERROR_NONE != __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, &sinkpad)) {
- wfd_sink_error("failed to prepare audio pipeline....");
- goto ERROR;
- }
-
- if (wfd_sink->pipeline->a_decodebin && wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst)
- decodebin = wfd_sink->pipeline->a_decodebin[WFD_SINK_A_D_BIN].gst;
- if (wfd_sink->pipeline->a_sinkbin && wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst)
- sinkbin = wfd_sink->pipeline->a_sinkbin[WFD_SINK_A_S_BIN].gst;
- } else {
- wfd_sink_error("unexceptable pad is added!!!");
- return;
+ 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);
- 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)));
+ gst_pad_add_probe(pad,
+ GST_PAD_PROBE_TYPE_BUFFER,
+ _mm_wfd_sink_check_running_time,
+ (gpointer)wfd_sink,
+ NULL);
+
+ if (MM_ERROR_NONE != __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &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') {
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;
stream_info = &wfd_sink->stream_info;
- audio_codec = wfd_sink->stream_info.audio_stream_info.codec;
- video_codec = wfd_sink->stream_info.video_stream_info.codec;
-
if (gst_structure_has_field(str, "audio_format")) {
is_valid_audio_format = TRUE;
audio_format = g_strdup(gst_structure_get_string(str, "audio_format"));
if (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 \n",
- audio_format,
- stream_info->audio_stream_info.sample_rate,
- stream_info->audio_stream_info.channels,
- stream_info->audio_stream_info.bitwidth);
+ audio_format,
+ stream_info->audio_stream_info.sample_rate,
+ stream_info->audio_stream_info.channels,
+ stream_info->audio_stream_info.bitwidth);
}
}
if (gst_structure_has_field(str, "video_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);
}
}
}
static void __mm_wfd_sink_prepare_video_resolution(gint resolution, guint64 *CEA_resolution,
- guint64 *VESA_resolution, guint64 *HH_resolution)
+ guint64 *VESA_resolution, guint64 *HH_resolution)
{
if (resolution == MM_WFD_SINK_RESOLUTION_UNKNOWN) return;
/* 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);
+ "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);
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);
+ &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);
+ "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);
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);
+ "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);
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);
+ "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);
if (wfd2_audio_codecs) {
g_object_set(G_OBJECT(wfdsrc), "wfd2-audio-codecs", wfd2_audio_codecs, NULL);
}
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_CALLBACK(__mm_wfd_sink_update_stream_info), 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);
+ G_CALLBACK(__mm_wfd_sink_change_av_format), wfd_sink);
wfd_sink_debug_fleave();
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_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);
- wfd_sink_warning("%s is overrun",
- GST_STR_NULL(GST_ELEMENT_NAME(element)));
+ g_object_get(G_OBJECT(queue), "current-level-time", &time, NULL);
+
+ 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-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_CALLBACK(__mm_wfd_sink_queue_overrun), wfd_sink);
wfd_sink_debug_fleave();
}
}
+ /* 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");
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");
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;
}
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;
}
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("%s has parent.(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(parent));
parent = 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_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.");
/* 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.wfd_audio_codecs.audio_codec;
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("%s has parent.(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(parent));
parent = 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;
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.");
/* create resampler */
MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_RESAMPLER,
- wfd_sink->ini.name_of_audio_resampler, "audio_resampler", TRUE);
+ 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);
+ wfd_sink->ini.name_of_audio_volume, "audio_volume", TRUE);
MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_VOLUME].gst, "sink");
MMWFDSINK_PAD_PROBE(wfd_sink, NULL, a_sinkbin[WFD_SINK_A_S_VOLUME].gst, "src");
/* create sink */
MMWFDSINK_CREATE_ELEMENT(a_sinkbin, WFD_SINK_A_S_SINK,
- wfd_sink->ini.name_of_audio_sink, "audio_sink", TRUE);
+ 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)) {
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;
}
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");
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;
}
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;
}
break;
case MM_DISPLAY_SURFACE_OVERLAY: {
+ static unsigned 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;
- unsigned int wl_surface_id = 0;
struct wl_surface *wl_surface = NULL;
struct wl_display *wl_display = NULL;
Ecore_Wl_Window *wl_window = NULL;
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_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("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 ret;
+ }
+ 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 (wlclient) {
- g_free(wlclient);
- wlclient = NULL;
- }
+ if (wlclient) {
+ g_free(wlclient);
+ wlclient = NULL;
+ }
+ }
wfd_sink_debug("set video param : surface_id %d", wl_surface_id);
gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(video_sink),
- wl_surface_id);
+ 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);
+ 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;
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("%s has parent.(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(parent));
parent = NULL;
}
/* release video decodebin with it's childs */
if (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_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");
/* 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);
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("%s has parent.(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(parent));
parent = 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;
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.");
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;
}
static 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 pipeline to NULL");
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;
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));
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 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();
+}