- sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
- LOGD("creating audiosink bin success\n");
- } else {
- reusing = TRUE;
- sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
- LOGD("reusing audiobin\n");
- _mmplayer_update_content_attrs(player, ATTR_AUDIO);
- }
-
- if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
- mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
-
- player->audiosink_linked = 1;
-
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
- if (!sinkpad) {
- LOGE("failed to get pad from sinkbin\n");
- goto ERROR;
- }
- } else if (strstr(name, "video")) {
- if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
- strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
- player->set_mode.video_zc = TRUE;
-
- if (player->pipeline->videobin == NULL) {
- /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
- /* get video surface type */
- int surface_type = 0;
- mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
- LOGD("display_surface_type(%d)\n", surface_type);
-
- if (surface_type == MM_DISPLAY_SURFACE_NULL) {
- LOGD("not make videobin because it dose not want\n");
- goto ERROR;
- }
-
- if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
- /* mark video overlay for acquire */
- if (player->video_overlay_resource == NULL) {
- if (mm_resource_manager_mark_for_acquire(player->resource_manager,
- MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
- MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
- &player->video_overlay_resource)
- != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not mark video_overlay resource for acquire\n");
- goto ERROR;
- }
- }
- }
-
- player->interrupted_by_resource = FALSE;
- /* acquire resources for video overlay */
- if (mm_resource_manager_commit(player->resource_manager) !=
- MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not acquire resources for video playing\n");
- goto ERROR;
- }
-
- if (MM_ERROR_NONE != __mmplayer_gst_create_video_pipeline(player, caps, surface_type)) {
- LOGE("failed to create videobin. continuing without video\n");
- goto ERROR;
- }
-
- sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
- LOGD("creating videosink bin success\n");
- } else {
- reusing = TRUE;
- sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
- LOGD("re-using videobin\n");
- _mmplayer_update_content_attrs(player, ATTR_VIDEO);
- }
-
- player->videosink_linked = 1;
-
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
- if (!sinkpad) {
- LOGE("failed to get pad from sinkbin\n");
- goto ERROR;
- }
- } else if (strstr(name, "text")) {
- if (player->pipeline->textbin == NULL) {
- MMPlayerGstElement* mainbin = NULL;
-
- if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) {
- LOGE("failed to create text sink bin. continuing without text\n");
- goto ERROR;
- }
-
- sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
- LOGD("creating textsink bin success\n");
-
- /* FIXIT : track number shouldn't be hardcoded */
- mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
-
- player->textsink_linked = 1;
- LOGI("player->textsink_linked set to 1\n");
-
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "text_sink");
- if (!sinkpad) {
- LOGE("failed to get pad from sinkbin\n");
- goto ERROR;
- }
-
- mainbin = player->pipeline->mainbin;
-
- if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst) {
- /* input selector */
- text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
- if (!text_selector) {
- LOGE("failed to create subtitle input selector element\n");
- goto ERROR;
- }
- g_object_set(text_selector, "sync-streams", TRUE, NULL);
-
- mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
- mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
-
- /* warm up */
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_READY)) {
- LOGE("failed to set state(READY) to sinkbin\n");
- goto ERROR;
- }
-
- if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector)) {
- LOGW("failed to add subtitle input selector\n");
- goto ERROR;
- }
-
- LOGD("created element input-selector");
-
- } else {
- LOGD("already having subtitle input selector");
- text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
- }
- } else {
- if (!player->textsink_linked) {
- LOGD("re-using textbin\n");
-
- reusing = TRUE;
- sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
-
- player->textsink_linked = 1;
- LOGI("player->textsink_linked set to 1\n");
- } else
- LOGD("ignoring internal subtutle since external subtitle is available");
- }
- } else {
- LOGW("unknown type of elementary stream!ignoring it...\n");
- goto ERROR;
- }
-
- if (sinkbin) {
- if (!reusing) {
- /* warm up */
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_READY)) {
- LOGE("failed to set state(READY) to sinkbin\n");
- goto ERROR;
- }
-
- /* Added for multi audio support to avoid adding audio bin again*/
- /* add */
- if (FALSE == gst_bin_add(GST_BIN(pipeline), sinkbin)) {
- LOGE("failed to add sinkbin to pipeline\n");
- goto ERROR;
- }
- }
-
- /* link */
- if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGE("failed to get pad from sinkbin\n");
- goto ERROR;
- }
-
- if (!reusing) {
- /* run */
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_PAUSED)) {
- LOGE("failed to set state(PAUSED) to sinkbin\n");
- goto ERROR;
- }
-
- if (text_selector) {
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_PAUSED)) {
- LOGE("failed to set state(PAUSED) to sinkbin\n");
- goto ERROR;
- }
- }
- }
-
- gst_object_unref(sinkpad);
- sinkpad = NULL;
- }
-
- LOGD("[handle: %p] linking sink bin success", player);
-
- /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
- * streaming task. if the task blocked, then buffer will not flow to the next element
- *(autoplugging element). so this is special hack for streaming. please try to remove it
- */
- /* dec stream count. we can remove fakesink if it's zero */
- if (player->num_dynamic_pad)
- player->num_dynamic_pad--;
-
- LOGD("no more pads: %d stream count dec : %d(num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
-
- if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
- __mmplayer_pipeline_complete(NULL, player);
-
-ERROR:
-
- MMPLAYER_FREEIF(caps_str);
-
- if (caps)
- gst_caps_unref(caps);
-
- if (sinkpad)
- gst_object_unref(GST_OBJECT(sinkpad));
-
- /* flusing out new attributes */
- if (mmf_attrs_commit(attrs))
- LOGE("failed to comit attributes\n");
-
- return;
-}
-
-static gboolean
-__mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
-{
- int pro_value = 0; // in the case of expection, default will be returned.
- int dest_angle = rotation_angle;
- int rotation_type = -1;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL(value, FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL(rotation_angle >= 0, FALSE);
-
- if (rotation_angle >= 360)
- dest_angle = rotation_angle - 360;
-
- /* chech if supported or not */
- if (dest_angle % 90) {
- LOGD("not supported rotation angle = %d", rotation_angle);
- return FALSE;
- }
-
- /*
- * tizenwlsink (A)
- * custom_convert - none (B)
- * videoflip - none (C)
- */
- if (player->set_mode.video_zc) {
- if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
- rotation_type = ROTATION_USING_CUSTOM;
- else // A
- rotation_type = ROTATION_USING_SINK;
- } else {
- int surface_type = 0;
- rotation_type = ROTATION_USING_FLIP;
-
- mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
- LOGD("check display surface type attribute: %d", surface_type);
-
- if (surface_type == MM_DISPLAY_SURFACE_OVERLAY)
- rotation_type = ROTATION_USING_SINK;
- else
- rotation_type = ROTATION_USING_FLIP; //C
-
- LOGD("using %d type for rotation", rotation_type);
- }
-
- /* get property value for setting */
- switch (rotation_type) {
- case ROTATION_USING_SINK: // tizenwlsink
- {
- switch (dest_angle) {
- case 0:
- break;
- case 90:
- pro_value = 3; // clockwise 90
- break;
- case 180:
- pro_value = 2;
- break;
- case 270:
- pro_value = 1; // counter-clockwise 90
- break;
- }
- }
- break;
- case ROTATION_USING_CUSTOM:
- {
- gchar *ename = NULL;
- ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
-
- if (g_strrstr(ename, "fimcconvert")) {
- switch (dest_angle) {
- case 0:
- break;
- case 90:
- pro_value = 90; // clockwise 90
- break;
- case 180:
- pro_value = 180;
- break;
- case 270:
- pro_value = 270; // counter-clockwise 90
- break;
- }
- }
- }
- break;
- case ROTATION_USING_FLIP: // videoflip
- {
- switch (dest_angle) {
- case 0:
- break;
- case 90:
- pro_value = 1; // clockwise 90
- break;
- case 180:
- pro_value = 2;
- break;
- case 270:
- pro_value = 3; // counter-clockwise 90
- break;
- }
- }
- break;
- }
-
- LOGD("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
-
- *value = pro_value;
-
- return TRUE;
-}
-
-int
-__mmplayer_video_param_check_video_sink_bin(mm_player_t* player)
-{
- /* check video sinkbin is created */
- MMPLAYER_RETURN_VAL_IF_FAIL(player &&
- player->pipeline &&
- player->pipeline->videobin &&
- player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
- player->pipeline->videobin[MMPLAYER_V_SINK].gst,
- MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- return MM_ERROR_NONE;
-}
-
-void
-__mmplayer_video_param_set_display_rotation(mm_player_t* player)
-{
- int rotation_value = 0;
- int org_angle = 0; // current supported angle values are 0, 90, 180, 270
- int user_angle = 0;
- MMPLAYER_FENTER();
-
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
- return;
-
- __mmplayer_get_video_angle(player, &user_angle, &org_angle);
-
- /* get rotation value to set */
- __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotation_value, NULL);
- LOGD("set video param : rotate %d", rotation_value);
-}
-
-void
-__mmplayer_video_param_set_display_visible(mm_player_t* player)
-{
- MMHandleType attrs = 0;
- int visible = 0;
- MMPLAYER_FENTER();
-
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
- return;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- MMPLAYER_RETURN_IF_FAIL(attrs);
-
- mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "visible", visible, NULL);
- LOGD("set video param : visible %d", visible);
-}
-
-void
-__mmplayer_video_param_set_display_method(mm_player_t* player)
-{
- MMHandleType attrs = 0;
- int display_method = 0;
- MMPLAYER_FENTER();
-
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
- return;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- MMPLAYER_RETURN_IF_FAIL(attrs);
-
- mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "display-geometry-method", display_method, NULL);
- LOGD("set video param : method %d", display_method);
-}
-
-void
-__mmplayer_video_param_set_render_rectangle(mm_player_t* player)
-{
- MMHandleType attrs = 0;
- void *handle = NULL;
- /*set wl_display*/
- int wl_window_x = 0;
- int wl_window_y = 0;
- int wl_window_width = 0;
- int wl_window_height = 0;
- MMPLAYER_FENTER();
-
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
- return;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- MMPLAYER_RETURN_IF_FAIL(attrs);
-
- mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
-
- if (handle) {
- /*It should be set after setting window*/
- mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
- mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
- mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
- mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
-
- /* After setting window handle, set render rectangle */
- gst_video_overlay_set_render_rectangle(
- GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- wl_window_x, wl_window_y, wl_window_width, wl_window_height);
- LOGD("set video param : render rectangle : x(%d) y(%d) width(%d) height(%d)",
- wl_window_x, wl_window_y, wl_window_width, wl_window_height);
-
- }
-}
-void
-__mmplayer_video_param_set_display_overlay(mm_player_t* player)
-{
- MMHandleType attrs = 0;
- void *handle = NULL;
-
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
- return;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- MMPLAYER_RETURN_IF_FAIL(attrs);
-
- /* common case if using overlay surface */
- mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
-
- if (handle) {
- /* default is using wl_surface_id */
- unsigned int wl_surface_id = 0;
- wl_surface_id = *(int*)handle;
- LOGD("set video param : wl_surface_id %d %p", wl_surface_id, *(int*)handle);
- gst_video_overlay_set_wl_window_wl_surface_id(
- GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- *(int*)handle);
- } else
- /* FIXIT : is it error case? */
- LOGW("still we don't have a window handle on player attribute. create it's own surface.");
-}
-
-
-int
-__mmplayer_update_wayland_videosink_video_param(mm_player_t* player, char *param_name)
-{
- bool update_all_param = FALSE;
- MMPLAYER_FENTER();
-
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
- return MM_ERROR_PLAYER_NOT_INITIALIZED;
-
- if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
- LOGE("can not find tizenwlsink");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- LOGD("param_name : %s", param_name);
- if (!g_strcmp0(param_name, "update_all_param"))
- update_all_param = TRUE;
-
- if (update_all_param || !g_strcmp0(param_name, "display_overlay"))
- __mmplayer_video_param_set_display_overlay(player);
- if (update_all_param || !g_strcmp0(param_name, "display_method"))
- __mmplayer_video_param_set_display_method(player);
- if (update_all_param || !g_strcmp0(param_name, "wl_window_render_x"))
- __mmplayer_video_param_set_render_rectangle(player);
- if (update_all_param || !g_strcmp0(param_name, "display_visible"))
- __mmplayer_video_param_set_display_visible(player);
- if (update_all_param || !g_strcmp0(param_name, "display_rotation"))
- __mmplayer_video_param_set_display_rotation(player);
-
- return MM_ERROR_NONE;
-}
-
-int
-_mmplayer_update_video_param(mm_player_t* player, char *param_name)
-{
- MMHandleType attrs = 0;
- int surface_type = 0;
- int ret = MM_ERROR_NONE;
-
- MMPLAYER_FENTER();
-
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
- return MM_ERROR_PLAYER_NOT_INITIALIZED;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("cannot get content attribute");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- LOGD("param_name : %s", param_name);
-
- /* update display surface */
- mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
- LOGD("check display surface type attribute: %d", surface_type);
-
- /* configuring display */
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_OVERLAY:
- {
- ret = __mmplayer_update_wayland_videosink_video_param(player, param_name);
- if (ret != MM_ERROR_NONE)
- return ret;
- }
- break;
- }
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-}
-
-int
-_mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
-{
- gboolean disable_overlay = FALSE;
- mm_player_t* player = (mm_player_t*) hplayer;
- int ret = MM_ERROR_NONE;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
- player->pipeline->videobin[MMPLAYER_V_SINK].gst,
- MM_ERROR_PLAYER_NO_OP); /* invalid op */
-
- if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
- LOGW("Display control is not supported");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
-
- if (audio_only == (bool)disable_overlay) {
- LOGE("It's the same with current setting: (%d)", audio_only);
- return MM_ERROR_NONE;
- }
-
- if (audio_only) {
- LOGE("disable overlay");
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL);
-
- /* release overlay resource */
- if (player->video_overlay_resource != NULL) {
- ret = mm_resource_manager_mark_for_release(player->resource_manager,
- player->video_overlay_resource);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
- goto ERROR;
- }
- player->video_overlay_resource = NULL;
- }
-
- ret = mm_resource_manager_commit(player->resource_manager);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("failed to commit acquiring of overlay resource, ret(0x%x)\n", ret);
- goto ERROR;
- }
- } else {
- /* mark video overlay for acquire */
- if (player->video_overlay_resource == NULL) {
- ret = mm_resource_manager_mark_for_acquire(player->resource_manager,
- MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
- MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
- &player->video_overlay_resource);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not prepare for video_overlay resource\n");
- goto ERROR;
- }
- }
-
- player->interrupted_by_resource = FALSE;
- /* acquire resources for video overlay */
- ret = mm_resource_manager_commit(player->resource_manager);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not acquire resources for video playing\n");
- goto ERROR;
- }
-
- LOGD("enable overlay");
- __mmplayer_video_param_set_display_overlay(player);
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", FALSE, NULL);
- }
-
-ERROR:
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
-}
-
-int
-_mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only)
-{
- mm_player_t* player = (mm_player_t*) hplayer;
- gboolean disable_overlay = FALSE;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(paudio_only, MM_ERROR_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
- player->pipeline->videobin[MMPLAYER_V_SINK].gst,
- MM_ERROR_PLAYER_NO_OP); /* invalid op */
-
- if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
- LOGW("Display control is not supported");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
-
- *paudio_only = (bool)(disable_overlay);
-
- LOGD("audio_only : %d", *paudio_only);
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-}
-
-static int
-__mmplayer_gst_element_link_bucket(GList* element_bucket)
-{
- GList* bucket = element_bucket;
- MMPlayerGstElement* element = NULL;
- MMPlayerGstElement* prv_element = NULL;
- gint successful_link_count = 0;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, -1);
-
- prv_element = (MMPlayerGstElement*)bucket->data;
- bucket = bucket->next;
-
- for (; bucket; bucket = bucket->next) {
- element = (MMPlayerGstElement*)bucket->data;
-
- if (element && element->gst) {
- /* If next element is audio appsrc then make a separate audio pipeline */
- if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "audio_appsrc") ||
- !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "subtitle_appsrc")) {
- prv_element = element;
- continue;
- }
-
- if (prv_element && prv_element->gst) {
- if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
- LOGD("linking [%s] to [%s] success\n",
- GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
- GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
- successful_link_count++;
- } else {
- LOGD("linking [%s] to [%s] failed\n",
- GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
- GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
- return -1;
- }
- }
- }
-
- prv_element = element;
- }
-
- MMPLAYER_FLEAVE();
-
- return successful_link_count;
-}
-
-static int
-__mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket)
-{
- GList* bucket = element_bucket;
- MMPlayerGstElement* element = NULL;
- int successful_add_count = 0;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, 0);
- MMPLAYER_RETURN_VAL_IF_FAIL(bin, 0);
-
- for (; bucket; bucket = bucket->next) {
- element = (MMPlayerGstElement*)bucket->data;
-
- if (element && element->gst) {
- if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
- LOGD("__mmplayer_gst_element_link_bucket : Adding element [%s] to bin [%s] failed\n",
- GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
- GST_ELEMENT_NAME(GST_ELEMENT(bin)));
- return 0;
- }
- successful_add_count++;
- }
- }
-
- MMPLAYER_FLEAVE();
-
- return successful_add_count;
-}
-
-static void __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data)
-{
- mm_player_t* player = (mm_player_t*) data;
- GstCaps *caps = NULL;
- GstStructure *str = NULL;
- const char *name;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_IF_FAIL(pad)
- MMPLAYER_RETURN_IF_FAIL(unused)
- MMPLAYER_RETURN_IF_FAIL(data)
-
- caps = gst_pad_get_current_caps(pad);
- if (!caps)
- return;
-
- str = gst_caps_get_structure(caps, 0);
- if (!str)
- goto ERROR;
-
- name = gst_structure_get_name(str);
- if (!name)
- goto ERROR;
-
- LOGD("name = %s\n", name);
-
- if (strstr(name, "audio")) {
- _mmplayer_update_content_attrs(player, ATTR_AUDIO);
-
- if (player->audio_stream_changed_cb) {
- LOGE("call the audio stream changed cb\n");
- player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
- }
- } else if (strstr(name, "video")) {
- if ((name = gst_structure_get_string(str, "format")))
- player->set_mode.video_zc = name[0] == 'S';
-
- _mmplayer_update_content_attrs(player, ATTR_VIDEO);
-
- if (player->video_stream_changed_cb) {
- LOGE("call the video stream changed cb\n");
- player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
- }
- } else
- goto ERROR;
-
-ERROR:
-
- gst_caps_unref(caps);
-
- MMPLAYER_FLEAVE();
-
- return;
-}
-
-
-
-/**
- * This function is to create audio pipeline for playing.
- *
- * @param player [in] handle of player
- *
- * @return This function returns zero on success.
- * @remark
- * @see __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
- */
-/* macro for code readability. just for sinkbin-creation functions */
-#define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
-do {\
- x_bin[x_id].id = x_id;\
- x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
- if (!x_bin[x_id].gst) {\
- LOGE("failed to create %s \n", x_factory);\
- goto ERROR;\
- } else {\
- if (x_player->ini.set_dump_element_flag)\
- __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
- } \
- if (x_add_bucket)\
- element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
-} while (0);
-
-static void
-__mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all)
-{
- GList *l = NULL;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player);
-
- if (player->audio_stream_buff_list) {
- for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
- mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
- if (tmp) {
- if (send_all) {
- LOGD("[%lld] send remained data.", tmp->channel_mask);
- __mmplayer_audio_stream_send_data(player, tmp);
- }
- if (tmp->pcm_data)
- g_free(tmp->pcm_data);
- g_free(tmp);
- }
- }
- g_list_free(player->audio_stream_buff_list);
- player->audio_stream_buff_list = NULL;
- }
-
- MMPLAYER_FLEAVE();
-}
-
-static void
-__mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer)
-{
- MMPlayerAudioStreamDataType audio_stream = { 0, };
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
-
- audio_stream.bitrate = a_buffer->bitrate;
- audio_stream.channel = a_buffer->channel;
- audio_stream.depth = a_buffer->depth;
- audio_stream.is_little_endian = a_buffer->is_little_endian;
- audio_stream.channel_mask = a_buffer->channel_mask;
- audio_stream.data_size = a_buffer->data_size;
- audio_stream.data = a_buffer->pcm_data;
-
- /* LOGD("[%lld] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_stream_cb_user_param); */
- player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
-
- MMPLAYER_FLEAVE();
-}
-
-static void
-__mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
-{
- mm_player_t* player = (mm_player_t*) data;
-
- gint channel = 0;
- gint rate = 0;
- gint depth = 0;
- gint endianness = 0;
- guint64 channel_mask = 0;
- void *a_data = NULL;
- gint a_size = 0;
- mm_player_audio_stream_buff_t *a_buffer = NULL;
- GstMapInfo mapinfo = GST_MAP_INFO_INIT;
- GList *l = NULL;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
-
- gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
- a_data = mapinfo.data;
- a_size = mapinfo.size;
-
- GstCaps *caps = gst_pad_get_current_caps(pad);
- GstStructure *structure = gst_caps_get_structure(caps, 0);
-
- /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
- gst_structure_get_int(structure, "rate", &rate);
- gst_structure_get_int(structure, "channels", &channel);
- gst_structure_get_int(structure, "depth", &depth);
- gst_structure_get_int(structure, "endianness", &endianness);
- gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
- gst_caps_unref(GST_CAPS(caps));
-
- /* In case of the sync is false, use buffer list. *
- * The num of buffer list depends on the num of audio channels */
- if (player->audio_stream_buff_list) {
- for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
- mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
- if (tmp) {
- if (channel_mask == tmp->channel_mask) {
- /* LOGD("[%lld] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); */
- if (tmp->data_size + a_size < tmp->buff_size) {
- memcpy(tmp->pcm_data + tmp->data_size, a_data, a_size);
- tmp->data_size += a_size;
- } else {
- /* send data to client */
- __mmplayer_audio_stream_send_data(player, tmp);
-
- if (a_size > tmp->buff_size) {
- LOGD("[%lld] adj buffer size %d -> %d", channel_mask, tmp->buff_size, a_size);
- tmp->pcm_data = g_realloc(tmp->pcm_data, a_size);
- if (tmp->pcm_data == NULL) {
- LOGE("failed to realloc data.");
- goto DONE;
- }
- tmp->buff_size = a_size;
- }
- memset(tmp->pcm_data, 0x00, tmp->buff_size);
- memcpy(tmp->pcm_data, a_data, a_size);
- tmp->data_size = a_size;
- }
- goto DONE;
- }
- } else {
- LOGE("data is empty in list.");
- goto DONE;
- }
- }
- }
-
- /* create new audio stream data */
- a_buffer = (mm_player_audio_stream_buff_t*)g_malloc0(sizeof(mm_player_audio_stream_buff_t));
- if (a_buffer == NULL) {
- LOGE("failed to alloc data.");
- goto DONE;
- }
- a_buffer->bitrate = rate;
- a_buffer->channel = channel;
- a_buffer->depth = depth;
- a_buffer->is_little_endian = (endianness == 1234 ? 1 : 0);
- a_buffer->channel_mask = channel_mask;
- a_buffer->data_size = a_size;
-
- if (!player->audio_stream_sink_sync) {
- /* If sync is FALSE, use buffer list to reduce the IPC. */
- a_buffer->buff_size = (a_size > player->ini.pcm_buffer_size) ? (a_size) : (player->ini.pcm_buffer_size);
- a_buffer->pcm_data = g_malloc(a_buffer->buff_size);
- if (a_buffer->pcm_data == NULL) {
- LOGE("failed to alloc data.");
- g_free(a_buffer);
- goto DONE;
- }
- memcpy(a_buffer->pcm_data, a_data, a_size);
- /* LOGD("new [%lld] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); */
- player->audio_stream_buff_list = g_list_append(player->audio_stream_buff_list, a_buffer);
- } else {
- /* If sync is TRUE, send data directly. */
- a_buffer->pcm_data = a_data;
- __mmplayer_audio_stream_send_data(player, a_buffer);
- g_free(a_buffer);
- }
-
-DONE:
- gst_buffer_unmap(buffer, &mapinfo);
- MMPLAYER_FLEAVE();
-}
-
-static void
-__mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
-{
- mm_player_t* player = (mm_player_t*)data;
- MMPlayerGstElement* audiobin = player->pipeline->audiobin;
- GstPad* sinkpad = NULL;
- GstElement *queue = NULL, *sink = NULL;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
-
- queue = gst_element_factory_make("queue", NULL);
- if (queue == NULL) {
- LOGD("fail make queue\n");
- goto ERROR;
- }
-
- sink = gst_element_factory_make("fakesink", NULL);
- if (sink == NULL) {
- LOGD("fail make fakesink\n");
- goto ERROR;
- }
-
- gst_bin_add_many(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
-
- if (!gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING)) {
- LOGW("failed to link queue & sink\n");
- goto ERROR;
- }
-
- sinkpad = gst_element_get_static_pad(queue, "sink");
-
- if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGW("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
- goto ERROR;
- }
-
- LOGE("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
-
- gst_object_unref(sinkpad);
- g_object_set(sink, "sync", player->audio_stream_sink_sync, NULL);
- g_object_set(sink, "signal-handoffs", TRUE, NULL);
-
- gst_element_set_state(sink, GST_STATE_PAUSED);
- gst_element_set_state(queue, GST_STATE_PAUSED);
-
- MMPLAYER_SIGNAL_CONNECT(player,
- G_OBJECT(sink),
- MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
- "handoff",
- G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
- (gpointer)player);
-
- MMPLAYER_FLEAVE();
- return;
-
-ERROR:
- LOGE("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
- if (queue) {
- gst_object_unref(GST_OBJECT(queue));
- queue = NULL;
- }
- if (sink) {
- gst_object_unref(GST_OBJECT(sink));
- sink = NULL;
- }
- if (sinkpad) {
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
- }
-
- return;
-}
-
-void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
-{
- #define MAX_PROPS_LEN 128
- gint latency_mode = 0;
- gchar *stream_type = NULL;
- gchar *latency = NULL;
- gint stream_id = 0;
- gchar stream_props[MAX_PROPS_LEN] = {0,};
- GstStructure *props = NULL;
-
- /* set volume table
- * It should be set after player creation through attribute.
- * But, it can not be changed during playing.
- */
- MMPLAYER_FENTER();
- mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
- mm_attrs_get_string_by_name(attrs, "sound_stream_type", &stream_type);
-
- if (!stream_type) {
- LOGE("stream_type is null.\n");
- } else {
- if (player->sound.focus_id)
- snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d, media.focus_id=%d",
- stream_type, stream_id, player->sound.focus_id);
- else
- snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d",
- stream_type, stream_id);
- props = gst_structure_from_string(stream_props, NULL);
- g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
- LOGI("stream_type[%s], stream_id[%d], focus_id[%d], result[%s].\n",
- stream_type, stream_id, player->sound.focus_id, stream_props);
- gst_structure_free(props);
- }
-
- mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
-
- switch (latency_mode) {
- case AUDIO_LATENCY_MODE_LOW:
- latency = g_strndup("low", 3);
- break;
- case AUDIO_LATENCY_MODE_MID:
- latency = g_strndup("mid", 3);
- break;
- case AUDIO_LATENCY_MODE_HIGH:
- latency = g_strndup("high", 4);
- break;
- };
-
- g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
- "latency", latency,
- NULL);
-
- LOGD("audiosink property - latency=%s \n", latency);
-
- g_free(latency);
-
- MMPLAYER_FLEAVE();
-}
-
-static int
-__mmplayer_gst_create_audio_pipeline(mm_player_t* player)
-{
- MMPlayerGstElement* first_element = NULL;
- MMPlayerGstElement* audiobin = NULL;
- MMHandleType attrs = 0;
- GstPad *pad = NULL;
- GstPad *ghostpad = NULL;
- GList* element_bucket = NULL;
- gboolean link_audio_sink_now = TRUE;
- int i = 0;
- GstCaps *acaps;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- /* alloc handles */
- audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
- if (!audiobin) {
- LOGE("failed to allocate memory for audiobin\n");
- return MM_ERROR_PLAYER_NO_FREE_SPACE;
- }
-
- attrs = MMPLAYER_GET_ATTRS(player);
-
- /* create bin */
- audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
- audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
- if (!audiobin[MMPLAYER_A_BIN].gst) {
- LOGE("failed to create audiobin\n");
- goto ERROR;
- }
-
- /* take it */
- player->pipeline->audiobin = audiobin;
-
- player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
-
- /* Adding audiotp plugin for reverse trickplay feature */
-// MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
-
- /* converter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
-
- /* replaygain volume */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RGVOL, "rgvolume", "audio rgvolume", TRUE, player);
- if (player->sound.rg_enable)
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", TRUE, NULL);
- else
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", FALSE, NULL);
-
- /* resampler */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER, player->ini.audioresampler_element, "audio resampler", TRUE, player);
-
- if (player->set_mode.pcm_extraction) {
- // pcm extraction only and no sound output
- if (player->audio_stream_render_cb_ex) {
- char *caps_str = NULL;
- GstCaps* caps = NULL;
- gchar *format = NULL;
-
- /* capsfilter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
-
- mm_attrs_get_string_by_name(player->attrs, "pcm_audioformat", &format);
-
- LOGD("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
-
- caps = gst_caps_new_simple("audio/x-raw",
- "format", G_TYPE_STRING, format,
- "rate", G_TYPE_INT, player->pcm_samplerate,
- "channels", G_TYPE_INT, player->pcm_channel,
- NULL);
- caps_str = gst_caps_to_string(caps);
- LOGD("new caps : %s\n", caps_str);
-
- g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
-
- /* clean */
- gst_caps_unref(caps);
- MMPLAYER_FREEIF(caps_str);
-
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
-
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
- /* raw pad handling signal */
- MMPLAYER_SIGNAL_CONNECT(player,
- (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
- MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
- G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
- } else {
- int dst_samplerate = 0;
- int dst_channels = 0;
- int dst_depth = 0;
- char *caps_str = NULL;
- GstCaps* caps = NULL;
-
- /* get conf. values */
- mm_attrs_multiple_get(player->attrs,
- NULL,
- "pcm_extraction_samplerate", &dst_samplerate,
- "pcm_extraction_channels", &dst_channels,
- "pcm_extraction_depth", &dst_depth,
- NULL);
-
- /* capsfilter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
- caps = gst_caps_new_simple("audio/x-raw",
- "rate", G_TYPE_INT, dst_samplerate,
- "channels", G_TYPE_INT, dst_channels,
- "depth", G_TYPE_INT, dst_depth,
- NULL);
- caps_str = gst_caps_to_string(caps);
- LOGD("new caps : %s\n", caps_str);
-
- g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
-
- /* clean */
- gst_caps_unref(caps);
- MMPLAYER_FREEIF(caps_str);
-
- /* fake sink */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
-
- /* set sync */
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
- }
- } else {
- // normal playback
- //GstCaps* caps = NULL;
- gint channels = 0;
-
- /* for logical volume control */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
-
- if (player->sound.mute) {
- LOGD("mute enabled\n");
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
- }
-
-#if 0
- /*capsfilter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
- caps = gst_caps_from_string("audio/x-raw-int, "
- "endianness = (int) LITTLE_ENDIAN, "
- "signed = (boolean) true, "
- "width = (int) 16, "
- "depth = (int) 16");
- g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
- gst_caps_unref(caps);
-#endif
-
- /* check if multi-channels */
- if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) {
- GstPad *srcpad = NULL;
- GstCaps *caps = NULL;
-
- if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src"))) {
- if ((caps = gst_pad_query_caps(srcpad, NULL))) {
- //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
- GstStructure *str = gst_caps_get_structure(caps, 0);
- if (str)
- gst_structure_get_int(str, "channels", &channels);
- gst_caps_unref(caps);
- }
- gst_object_unref(srcpad);
- }
- }
-
- /* audio effect element. if audio effect is enabled */
- if ((strcmp(player->ini.audioeffect_element, ""))
- && (channels <= 2)
- && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
-
- LOGD("audio effect config. bypass = %d, effect type = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
-
- if ((!player->bypass_audio_effect)
- && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
- if (MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type) {
- if (!_mmplayer_audio_effect_custom_apply(player))
- LOGI("apply audio effect(custom) setting success\n");
- }
- }
-
- if ((strcmp(player->ini.audioeffect_element_custom, ""))
- && (player->set_mode.rich_audio))
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
- }
-
- /* create audio sink */
- LOGD("360 spherical %d, channels %d, ambisonic type %d, format %d, order %d",
- player->is_content_spherical, channels, player->video360_metadata.ambisonic_type,
- player->video360_metadata.ambisonic_format, player->video360_metadata.ambisonic_order);
-
- /* Note: qtdemux converts audio metadata defaults to openalsink defaults. */
- if (player->is_360_feature_enabled &&
- player->is_content_spherical &&
- channels == 4 &&
- player->video360_metadata.ambisonic_type == MMFILE_AMBISONIC_TYPE_PERIPHONIC &&
- player->video360_metadata.ambisonic_format == MMFILE_AMBISONIC_FORMAT_AMB &&
- player->video360_metadata.ambisonic_order == MMFILE_AMBISONIC_ORDER_FOA) {
-
- strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
-
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", link_audio_sink_now, player);
-
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_360, "capsfilter", "audio-caps-filter", link_audio_sink_now, player);
- acaps = gst_caps_from_string(SPATIAL_AUDIO_CAPS);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_CAPS_360].gst), "caps", acaps, NULL);
- gst_caps_unref(acaps);
-
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "openalsink", "audiosink", link_audio_sink_now, player);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL);
- sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
-
- player->is_openal_plugin_used = TRUE;
-
- if (player->video360_yaw_radians <= M_PI &&
- player->video360_yaw_radians >= -M_PI &&
- player->video360_pitch_radians <= M_PI_2 &&
- player->video360_pitch_radians >= -M_PI_2) {
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
- "source-orientation-y", (int) (player->video360_yaw_radians * 180.0 / M_PI),
- "source-orientation-x", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
- } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
- "source-orientation-y", player->video360_metadata.init_view_heading,
- "source-orientation-x", player->video360_metadata.init_view_pitch, NULL);
- }
- } else {
- if (player->is_360_feature_enabled && player->is_content_spherical)
- LOGW("Audio track isn't of the ambisonic type and can't be played back as a spatial sound.\n");
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", link_audio_sink_now, player);
- }
-
- /* qos on */
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
-
-
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
- (player->videodec_linked && player->ini.use_system_clock)) {
- LOGD("system clock will be used.\n");
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE, NULL);
- }
-
- if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
- __mmplayer_gst_set_audiosink_property(player, attrs);
- }
-
- if (audiobin[MMPLAYER_A_SINK].gst) {
- GstPad *sink_pad = NULL;
- sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
- MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
- "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
- gst_object_unref(GST_OBJECT(sink_pad));
- }
-
- __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
-
- /* adding created elements to bin */
- LOGD("adding created elements to bin\n");
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket)) {
- LOGE("failed to add elements\n");
- goto ERROR;
- }
-
- /* linking elements in the bucket by added order. */
- LOGD("Linking elements in the bucket by added order.\n");
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
- LOGE("failed to link elements\n");
- goto ERROR;
- }
-
- /* get first element's sinkpad for creating ghostpad */
- first_element = (MMPlayerGstElement *)element_bucket->data;
- if (!first_element) {
- LOGE("failed to get first elem\n");
- goto ERROR;
- }
-
- pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
- if (!pad) {
- LOGE("failed to get pad from first element of audiobin\n");
- goto ERROR;
- }
-
- ghostpad = gst_ghost_pad_new("sink", pad);
- if (!ghostpad) {
- LOGE("failed to create ghostpad\n");
- goto ERROR;
- }
-
- if (FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad)) {
- LOGE("failed to add ghostpad to audiobin\n");
- goto ERROR;
- }
-
- gst_object_unref(pad);
-
- g_list_free(element_bucket);
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-
-ERROR:
-
- LOGD("ERROR : releasing audiobin\n");
-
- if (pad)
- gst_object_unref(GST_OBJECT(pad));
-
- if (ghostpad)
- gst_object_unref(GST_OBJECT(ghostpad));
-
- if (element_bucket)
- g_list_free(element_bucket);
-
- /* release element which are not added to bin */
- for (i = 1; i < MMPLAYER_A_NUM; i++) {
- /* NOTE : skip bin */
- if (audiobin[i].gst) {
- GstObject* parent = NULL;
- parent = gst_element_get_parent(audiobin[i].gst);
-
- if (!parent) {
- gst_object_unref(GST_OBJECT(audiobin[i].gst));
- audiobin[i].gst = NULL;
- } else
- gst_object_unref(GST_OBJECT(parent));
- }
- }
-
- /* release audiobin with it's childs */
- if (audiobin[MMPLAYER_A_BIN].gst)
- gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
-
- MMPLAYER_FREEIF(audiobin);
-
- player->pipeline->audiobin = NULL;
-
- return MM_ERROR_PLAYER_INTERNAL;
-}
-
-static GstPadProbeReturn
-__mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
-{
- mm_player_t* player = (mm_player_t*) u_data;
- GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
- GstMapInfo probe_info = GST_MAP_INFO_INIT;
-
- gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
-
- if (player->audio_stream_cb && probe_info.size && probe_info.data)
- player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
-
- return GST_PAD_PROBE_OK;
-}
-
-static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
-{
- return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
-}
-
-int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo)
-{
- int ret = MM_ERROR_NONE;
- GList *l = NULL;
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_INVALID_ARGUMENT);
-
- MMPLAYER_VIDEO_BO_LOCK(player);
-
- if (player->video_bo_list) {
- for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
- mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
- if (tmp && tmp->bo == bo) {
- tmp->using = FALSE;
- LOGD("release bo %p", bo);
- tbm_bo_unref(tmp->bo);
- MMPLAYER_VIDEO_BO_UNLOCK(player);
- MMPLAYER_VIDEO_BO_SIGNAL(player);
- return ret;
- }
- }
- } else {
- /* hw codec is running or the list was reset for DRC. */
- LOGW("there is no bo list.");
- }
- MMPLAYER_VIDEO_BO_UNLOCK(player);
-
- LOGW("failed to find bo %p", bo);
- return ret;
-}
-
-static void
-__mmplayer_video_stream_destroy_bo_list(mm_player_t* player)
-{
- GList *l = NULL;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player);
-
- MMPLAYER_VIDEO_BO_LOCK(player);
- if (player->video_bo_list) {
- LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
- for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
- mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
- if (tmp) {
- if (tmp->bo)
- tbm_bo_unref(tmp->bo);
- g_free(tmp);
- }
- }
- g_list_free(player->video_bo_list);
- player->video_bo_list = NULL;
- }
- player->video_bo_size = 0;
- MMPLAYER_VIDEO_BO_UNLOCK(player);
-
- MMPLAYER_FLEAVE();
- return;
-}
-
-static void*
-__mmplayer_video_stream_get_bo(mm_player_t* player, int size)
-{
- GList *l = NULL;
- MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
- gboolean ret = TRUE;
-
- /* check DRC, if it is, destroy the prev bo list to create again */
- if (player->video_bo_size != size) {
- LOGD("video size is changed: %d -> %d", player->video_bo_size, size);
- __mmplayer_video_stream_destroy_bo_list(player);
- player->video_bo_size = size;
- }
-
- MMPLAYER_VIDEO_BO_LOCK(player);
-
- if ((!player->video_bo_list) ||
- (g_list_length(player->video_bo_list) < player->ini.num_of_video_bo)) {
-
- /* create bo list */
- int idx = 0;
- LOGD("Create bo list for decoded video stream(num:%d)", player->ini.num_of_video_bo);
-
- if (player->video_bo_list) {
- /* if bo list did not created all, try it again. */
- idx = g_list_length(player->video_bo_list);
- LOGD("bo list exist(len: %d)", idx);
- }
-
- for (; idx < player->ini.num_of_video_bo; idx++) {
- mm_player_video_bo_info_t* bo_info = g_new(mm_player_video_bo_info_t, 1);
- if (!bo_info) {
- LOGE("Fail to alloc bo_info.");
- break;
- }
- bo_info->bo = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
- if (!bo_info->bo) {
- LOGE("Fail to tbm_bo_alloc.");
- g_free(bo_info);
- break;
- }
- bo_info->using = FALSE;
- player->video_bo_list = g_list_append(player->video_bo_list, bo_info);
- }
-
- /* update video num buffers */
- player->video_num_buffers = idx;
- if (idx == player->ini.num_of_video_bo)
- player->video_extra_num_buffers = player->ini.num_of_video_bo/2;
-
- if (idx == 0) {
- MMPLAYER_VIDEO_BO_UNLOCK(player);
- return NULL;
- }
-
- LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers);
- }
-
- while (TRUE) {
- /* get bo from list*/
- for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
- mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
- if (tmp && (tmp->using == FALSE)) {
- LOGD("found bo %p to use", tmp->bo);
- tmp->using = TRUE;
- MMPLAYER_VIDEO_BO_UNLOCK(player);
- return tbm_bo_ref(tmp->bo);
- }
- }
- if (!ret) {
- LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
- MMPLAYER_VIDEO_BO_UNLOCK(player);
- return NULL;
- }
-
- if (player->ini.video_bo_timeout <= 0) {
- MMPLAYER_VIDEO_BO_WAIT(player);
- } else {
- gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout*G_TIME_SPAN_SECOND;
- ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
- }
- continue;
- }
-}
-
-static void
-__mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
-{
- mm_player_t* player = (mm_player_t*)data;
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
-
- /* send prerolled pkt */
- player->video_stream_prerolled = FALSE;
-
- __mmplayer_video_stream_decoded_render_cb(object, buffer, pad, data);
-
- /* not to send prerolled pkt again */
- player->video_stream_prerolled = TRUE;
-}
-
-static void
-__mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
-{
- mm_player_t* player = (mm_player_t*)data;
- GstCaps *caps = NULL;
- MMPlayerVideoStreamDataType *stream = NULL;
- MMVideoBuffer *video_buffer = NULL;
- GstMemory *dataBlock = NULL;
- GstMemory *metaBlock = NULL;
- GstMapInfo mapinfo = GST_MAP_INFO_INIT;
- GstStructure *structure = NULL;
- const gchar *string_format = NULL;
- unsigned int fourcc = 0;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
-
- if (player->video_stream_prerolled) {
- player->video_stream_prerolled = FALSE;
- LOGD("skip the prerolled pkt not to send it again");
- return;
- }
-
- caps = gst_pad_get_current_caps(pad);
- if (caps == NULL) {
- LOGE("Caps is NULL.");
- return;
- }
-
- /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
-
- /* clear stream data structure */
- stream = (MMPlayerVideoStreamDataType *)g_malloc0(sizeof(MMPlayerVideoStreamDataType));
- if (!stream) {
- LOGE("failed to alloc mem for video data");
- return;
- }
-
- structure = gst_caps_get_structure(caps, 0);
- gst_structure_get_int(structure, "width", &(stream->width));
- gst_structure_get_int(structure, "height", &(stream->height));
- string_format = gst_structure_get_string(structure, "format");
- if (string_format)
- fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
- stream->format = util_get_pixtype(fourcc);
- gst_caps_unref(caps);
- caps = NULL;
-
- /*
- LOGD("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
- GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format);
- */
-
- if (stream->width == 0 || stream->height == 0 || stream->format == MM_PIXEL_FORMAT_INVALID) {
- LOGE("Wrong condition!!");
- goto ERROR;
- }
-
- /* set size and timestamp */
- dataBlock = gst_buffer_peek_memory(buffer, 0);
- stream->length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
- stream->timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */
-
- /* check zero-copy */
- if (player->set_mode.video_zc &&
- player->set_mode.media_packet_video_stream &&
- gst_buffer_n_memory(buffer) > 1) {
- metaBlock = gst_buffer_peek_memory(buffer, 1);
- gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
- video_buffer = (MMVideoBuffer *)mapinfo.data;
- }
-
- if (video_buffer) { /* hw codec */
- /* set tbm bo */
- if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
- int i = 0;
-
- /* copy pointer of tbm bo, stride, elevation */
- while (i < MM_VIDEO_BUFFER_PLANE_MAX && video_buffer->handle.bo[i]) {
- stream->bo[i] = tbm_bo_ref(video_buffer->handle.bo[i]);
- i++;
- }
- } else {
- LOGE("Not support video buffer format");
- goto ERROR;
- }
- memcpy(stream->stride, video_buffer->stride_width,
- sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
- memcpy(stream->elevation, video_buffer->stride_height,
- sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
-
- /* will be released, by calling _mm_player_video_stream_internal_buffer_unref() */
- stream->internal_buffer = gst_buffer_ref(buffer);
- } else { /* sw codec */
- int i = 0;
- int j = 0;
- int k = 0;
- int ret = TBM_SURFACE_ERROR_NONE;
- int src_stride[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
- int src_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
- int size = 0;
- unsigned char *src = NULL;
- unsigned char *dest = NULL;
- tbm_bo_handle thandle;
- tbm_surface_h surface;
- tbm_surface_info_s info;
- gboolean gst_ret;
-
- gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
- if (!gst_ret) {
- LOGE("fail to gst_memory_map");
- goto ERROR;
- }
-
-
- if (stream->format == MM_PIXEL_FORMAT_I420) {
- surface = tbm_surface_create(stream->width, stream->height, TBM_FORMAT_YUV420);
-
- ret = tbm_surface_get_info(surface, &info);
-
- if (ret != TBM_SURFACE_ERROR_NONE) {
- tbm_surface_destroy(surface);
- goto ERROR;
- }
- tbm_surface_destroy(surface);
-
- src_stride[0] = GST_ROUND_UP_4(stream->width);
- src_stride[1] = src_stride[2] = GST_ROUND_UP_4(stream->width>>1);
- src_offset[1] = src_stride[0] * GST_ROUND_UP_2(stream->height);
- src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(stream->height)>>1));
- stream->stride[0] = info.planes[0].stride;
- stream->elevation[0] = info.planes[0].size / info.planes[0].stride;
- stream->stride[1] = info.planes[1].stride;
- stream->elevation[1] = info.planes[1].size / info.planes[1].stride;
- stream->stride[2] = info.planes[2].stride;
- stream->elevation[2] = info.planes[2].size / info.planes[2].stride;
- size = info.planes[0].size + info.planes[1].size + info.planes[2].size;
- } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
- stream->stride[0] = stream->width * 4;
- stream->elevation[0] = stream->height;
- size = stream->stride[0] * stream->height;
- } else {
- LOGE("Not support format %d", stream->format);
- goto ERROR;
- }
-
- stream->bo[0] = __mmplayer_video_stream_get_bo(player, size);
- if (!stream->bo[0]) {
- LOGE("Fail to tbm_bo_alloc!!");
- goto ERROR;
- }
-
- thandle = tbm_bo_map(stream->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
- if (thandle.ptr && mapinfo.data) {
- if (stream->format == MM_PIXEL_FORMAT_I420) {
- for (i = 0; i < 3; i++) {
- src = mapinfo.data + src_offset[i];
- dest = thandle.ptr + info.planes[i].offset;
-
- if (i > 0) k = 1;
- for (j = 0; j < stream->height>>k; j++) {
- memcpy(dest, src, stream->width>>k);
- src += src_stride[i];
- dest += stream->stride[i];
- }
- }
- } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
- memcpy(thandle.ptr, mapinfo.data, size);
- } else {
- LOGE("Not support format %d", stream->format);
- goto ERROR;
- }
- } else {
- LOGE("data pointer is wrong. dest : %p, src : %p",
- thandle.ptr, mapinfo.data);
- goto ERROR;
- }
- tbm_bo_unmap(stream->bo[0]);
- }
-
- if (player->video_stream_cb) { /* This has been already checked at the entry */
- if (!player->video_stream_cb(stream, player->video_stream_cb_user_param)) {
- LOGE("failed to send video stream data.");
- goto ERROR;
- }
- }
-
- if (metaBlock)
- gst_memory_unmap(metaBlock, &mapinfo);
- else
- gst_memory_unmap(dataBlock, &mapinfo);
-
- return;
-
-ERROR:
- LOGE("release video stream resource.");
- if (metaBlock) {
- int i = 0;
- for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) {
- if (stream->bo[i])
- tbm_bo_unref(stream->bo[i]);
- }
- gst_memory_unmap(metaBlock, &mapinfo);
-
- /* unref gst buffer */
- if (stream->internal_buffer)
- gst_buffer_unref(stream->internal_buffer);
- } else if (dataBlock) {
- if (stream->bo[0])
- _mmplayer_video_stream_release_bo(player, stream->bo[0]);
- gst_memory_unmap(dataBlock, &mapinfo);
- }
-
- g_free(stream);
- return;
-}
-
-static int
-__mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket)
-{
- gchar* video_csc = "videoconvert"; /* default colorspace converter */
- GList* element_bucket = NULL;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- MMPLAYER_FENTER();
-
- if (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical)) {
- LOGD("do not need to add video filters.");
- return MM_ERROR_NONE;
- }
-
- /* in case of sw codec except 360 playback,
- * if libav video decoder is selected, videoconvert is required to render the shm wl-buffer which support RGB only via tizenwlsink. */
- MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
- LOGD("using video converter: %s", video_csc);
-
- /* set video rotator */
- MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
-
- *bucket = element_bucket;
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
-
-ERROR: /* refer MMPLAYER_CREATE_ELEMENT */
- g_list_free(element_bucket);
-
- *bucket = NULL;
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
-}
-
-/**
- * This function is to create video pipeline.
- *
- * @param player [in] handle of player
- * caps [in] src caps of decoder
- * surface_type [in] surface type for video rendering
- *
- * @return This function returns zero on success.
- * @remark
- * @see __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
- */
-/**
- * VIDEO PIPELINE
- * - video overlay surface(arm/x86) : tizenwlsink
- */
-static int
-__mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
-{
- GstPad *pad = NULL;
- MMHandleType attrs;
- GList*element_bucket = NULL;
- MMPlayerGstElement* first_element = NULL;
- MMPlayerGstElement* videobin = NULL;
- gchar *videosink_element = NULL;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- /* alloc handles */
- videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
- if (!videobin)
- return MM_ERROR_PLAYER_NO_FREE_SPACE;
-
- player->pipeline->videobin = videobin;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("cannot get content attribute");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* create bin */
- videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
- videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
- if (!videobin[MMPLAYER_V_BIN].gst) {
- LOGE("failed to create videobin");
- goto ERROR;
- }
-
- int enable_video_decoded_cb = 0;
- mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable_video_decoded_cb);
-
- if (player->is_360_feature_enabled && player->is_content_spherical) {
- LOGD("video360 elem will be added.");
-
- MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_360, "video360",
- "video-360", TRUE, player);
-
- /* Set spatial media metadata and/or user settings to the element.
- * */
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "projection-type", player->video360_metadata.projection_type, NULL);
-
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "stereo-mode", player->video360_metadata.stereo_mode, NULL);
-
- if (player->video360_metadata.full_pano_width_pixels &&
- player->video360_metadata.full_pano_height_pixels &&
- player->video360_metadata.cropped_area_image_width &&
- player->video360_metadata.cropped_area_image_height) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "projection-bounds-top", player->video360_metadata.cropped_area_top,
- "projection-bounds-bottom", player->video360_metadata.full_pano_height_pixels -
- player->video360_metadata.cropped_area_top - player->video360_metadata.cropped_area_image_height,
- "projection-bounds-left", player->video360_metadata.cropped_area_left,
- "projection-bounds-right", player->video360_metadata.full_pano_width_pixels -
- player->video360_metadata.cropped_area_left - player->video360_metadata.cropped_area_image_width,
- NULL);
- }
-
- if (player->video360_horizontal_fov && player->video360_vertical_fov) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "horizontal-fov", player->video360_horizontal_fov,
- "vertical-fov", player->video360_vertical_fov, NULL);
- }
-
- if (player->video360_zoom <= VIDEO360_MAX_ZOOM && player->video360_zoom > 1.0f) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "zoom", 1.0f / player->video360_zoom, NULL);
- }
-
- if (player->video360_yaw_radians <= M_PI &&
- player->video360_yaw_radians >= -M_PI &&
- player->video360_pitch_radians <= M_PI_2 &&
- player->video360_pitch_radians >= -M_PI_2) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "pose-yaw", (int) (player->video360_yaw_radians * 180.0 / M_PI),
- "pose-pitch", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
- } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "pose-yaw", player->video360_metadata.init_view_heading,
- "pose-pitch", player->video360_metadata.init_view_pitch, NULL);
- }
-
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "passthrough", !player->is_video360_enabled, NULL);
- }
-
- /* set video sink */
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_OVERLAY:
- if (__mmplayer_gst_create_video_filters(player, &element_bucket) != MM_ERROR_NONE)
- goto ERROR;
- if (strlen(player->ini.videosink_element_overlay) > 0)
- videosink_element = player->ini.videosink_element_overlay;
- else
- goto ERROR;
- break;
- case MM_DISPLAY_SURFACE_NULL:
- if (strlen(player->ini.videosink_element_fake) > 0)
- videosink_element = player->ini.videosink_element_fake;
- else
- goto ERROR;
- break;
- case MM_DISPLAY_SURFACE_REMOTE:
- if (strlen(player->ini.videosink_element_fake) > 0)
- videosink_element = player->ini.videosink_element_fake;
- else
- goto ERROR;
- break;
- default:
- LOGE("unidentified surface type");
- goto ERROR;
- }
- LOGD("surface_type %d, selected videosink name: %s", surface_type, videosink_element);
-
- MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, "videosink", TRUE, player);
-
- /* additional setting for sink plug-in */
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_OVERLAY:
- {
- bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
- if (!use_tbm) {
- LOGD("selected videosink name: %s", videosink_element);
-
- /* support shard memory with S/W codec on HawkP */
- if (strncmp(videosink_element, "tizenwlsink", strlen(videosink_element)) == 0) {
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
- "use-tbm", use_tbm, NULL);
- }
- } else {
- if (attrs) {
- int gapless = 0;
-
- mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
-
- if (gapless > 0) {
- LOGD("disable last-sample");
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
- }
- }
- }
- if (player->set_mode.media_packet_video_stream) {
- int enable = 0;
- mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable);
- if (enable)
- g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "signal-handoffs", TRUE, NULL);
-
- MMPLAYER_SIGNAL_CONNECT(player,
- G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "handoff",
- G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
- (gpointer)player);
-
- MMPLAYER_SIGNAL_CONNECT(player,
- G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "preroll-handoff",
- G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
- (gpointer)player);
- }
- break;
- }
- case MM_DISPLAY_SURFACE_REMOTE:
- {
- if (player->set_mode.media_packet_video_stream) {
- LOGE("add data probe at videosink");
- g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- "sync", TRUE, "signal-handoffs", TRUE, NULL);
-
- MMPLAYER_SIGNAL_CONNECT(player,
- G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "handoff",
- G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
- (gpointer)player);
-
- MMPLAYER_SIGNAL_CONNECT(player,
- G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "preroll-handoff",
- G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
- (gpointer)player);
- if (attrs) {
- int gapless = 0;
-
- mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
-
- if (gapless > 0) {
- LOGD("disable last-sample");
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
- }
- }
- }
- break;
- }
- default:
- break;
- }
-
- if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE)
- goto ERROR;
-
- if (videobin[MMPLAYER_V_SINK].gst) {
- GstPad *sink_pad = NULL;
- sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
- if (sink_pad) {
- MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
- gst_object_unref(GST_OBJECT(sink_pad));
- } else
- LOGW("failed to get sink pad from videosink\n");
- }
-
- /* store it as it's sink element */
- __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst);
-
- /* adding created elements to bin */
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
- LOGE("failed to add elements\n");
- goto ERROR;
- }
-
- /* Linking elements in the bucket by added order */
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
- LOGE("failed to link elements\n");
- goto ERROR;
- }
-
- /* get first element's sinkpad for creating ghostpad */
- if (element_bucket)
- first_element = (MMPlayerGstElement *)element_bucket->data;
- if (!first_element) {
- LOGE("failed to get first element from bucket\n");
- goto ERROR;
- }
-
- pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
- if (!pad) {
- LOGE("failed to get pad from first element\n");
- goto ERROR;
- }
-
- /* create ghostpad */
- player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
- if (FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
- LOGE("failed to add ghostpad to videobin\n");
- goto ERROR;
- }
- gst_object_unref(pad);
-
- /* done. free allocated variables */
- if (element_bucket)
- g_list_free(element_bucket);
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-
-ERROR:
- LOGE("ERROR : releasing videobin\n");
-
- g_list_free(element_bucket);
-
- if (pad)
- gst_object_unref(GST_OBJECT(pad));
-
- /* release videobin with it's childs */
- if (videobin[MMPLAYER_V_BIN].gst)
- gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
-
-
- MMPLAYER_FREEIF(videobin);
-
- player->pipeline->videobin = NULL;
-
- return MM_ERROR_PLAYER_INTERNAL;
-}
-
-static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
-{
- GList *element_bucket = NULL;
- MMPlayerGstElement *textbin = player->pipeline->textbin;
-
- MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
- MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
- g_object_set(G_OBJECT(textbin[MMPLAYER_T_IDENTITY].gst),
- "signal-handoffs", FALSE,
- NULL);
-
- MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
- MMPLAYER_SIGNAL_CONNECT(player,
- G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
- MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
- "handoff",
- G_CALLBACK(__mmplayer_update_subtitle),
- (gpointer)player);
-
- g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
- g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
- g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
-
- if (!player->play_subtitle) {
- LOGD("add textbin sink as sink element of whole pipeline.\n");
- __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
- }
-
- /* adding created elements to bin */
- LOGD("adding created elements to bin\n");
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
- LOGE("failed to add elements\n");
- goto ERROR;
- }
-
- /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
- GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
- GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
-
- /* linking elements in the bucket by added order. */
- LOGD("Linking elements in the bucket by added order.\n");
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
- LOGE("failed to link elements\n");
- goto ERROR;
- }
-
- /* done. free allocated variables */
- g_list_free(element_bucket);
-
- if (textbin[MMPLAYER_T_QUEUE].gst) {
- GstPad *pad = NULL;
- GstPad *ghostpad = NULL;
-
- pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
- if (!pad) {
- LOGE("failed to get sink pad of text queue");
- goto ERROR;
- }
-
- ghostpad = gst_ghost_pad_new("text_sink", pad);
- gst_object_unref(pad);
-
- if (!ghostpad) {
- LOGE("failed to create ghostpad of textbin\n");
- goto ERROR;
- }
-
- if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) {
- LOGE("failed to add ghostpad to textbin\n");
- gst_object_unref(ghostpad);
- goto ERROR;
- }
- }
-
- return MM_ERROR_NONE;
-
-ERROR:
- g_list_free(element_bucket);
-
- if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) {
- LOGE("remove textbin sink from sink list");
- __mmplayer_del_sink(player, textbin[MMPLAYER_T_FAKE_SINK].gst);
- }
-
- /* release element at __mmplayer_gst_create_text_sink_bin */
- return MM_ERROR_PLAYER_INTERNAL;
-}
-
-static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player)
-{
- MMPlayerGstElement *textbin = NULL;
- GList *element_bucket = NULL;
- int surface_type = 0;
- gint i = 0;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- /* alloc handles */
- textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
- if (!textbin) {
- LOGE("failed to allocate memory for textbin\n");
- return MM_ERROR_PLAYER_NO_FREE_SPACE;
- }
-
- /* create bin */
- textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
- textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
- if (!textbin[MMPLAYER_T_BIN].gst) {
- LOGE("failed to create textbin\n");
- goto ERROR;
- }
-
- /* take it */
- player->pipeline->textbin = textbin;
-
- /* fakesink */
- mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
- LOGD("surface type for subtitle : %d", surface_type);
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_OVERLAY:
- case MM_DISPLAY_SURFACE_NULL:
- case MM_DISPLAY_SURFACE_REMOTE:
- if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE) {
- LOGE("failed to make plain text elements\n");
- goto ERROR;
- }
- break;
- default:
- goto ERROR;
- break;
- }
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-
-ERROR:
-
- LOGD("ERROR : releasing textbin\n");
-
- g_list_free(element_bucket);
-
- /* release signal */
- __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
-
- /* release element which are not added to bin */
- for (i = 1; i < MMPLAYER_T_NUM; i++) {
- /* NOTE : skip bin */
- if (textbin[i].gst) {
- GstObject* parent = NULL;
- parent = gst_element_get_parent(textbin[i].gst);
-
- if (!parent) {
- gst_object_unref(GST_OBJECT(textbin[i].gst));
- textbin[i].gst = NULL;
- } else {
- gst_object_unref(GST_OBJECT(parent));
- }
- }
- }
-
- /* release textbin with it's childs */
- if (textbin[MMPLAYER_T_BIN].gst)
- gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));