From 1fc7c01a7e6047b0131c68236f2828847d20ff40 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Thu, 1 Jun 2017 20:32:11 +0900 Subject: [PATCH] [0.6.52] add subtitle error handling - make right error return - release resource in case of subtitle error to main pipeline make work Change-Id: I7c0c1bb6c172d807a82cca0b122d9aedf69d9551 --- packaging/libmm-player.spec | 2 +- src/mm_player_priv.c | 167 ++++++++++++++++++++++++++++++-------------- 2 files changed, 116 insertions(+), 53 deletions(-) diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index a1ea7fe..89785bc 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -1,6 +1,6 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.6.51 +Version: 0.6.52 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index a79d4ff..a01e72d 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -128,12 +128,12 @@ /*--------------------------------------------------------------------------- | LOCAL FUNCTION PROTOTYPES: | ---------------------------------------------------------------------------*/ +static int __mmplayer_gst_create_pipeline(mm_player_t* player); +static int __mmplayer_gst_destroy_pipeline(mm_player_t* player); static int __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type); static int __mmplayer_gst_create_audio_pipeline(mm_player_t* player); static int __mmplayer_gst_create_text_pipeline(mm_player_t* player); -static int __mmplayer_gst_create_subtitle_src(mm_player_t* player); -static int __mmplayer_gst_create_pipeline(mm_player_t* player); -static int __mmplayer_gst_destroy_pipeline(mm_player_t* player); +static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player); static int __mmplayer_gst_element_link_bucket(GList* element_bucket); static GstPadProbeReturn __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data); @@ -3622,8 +3622,8 @@ __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // if (player->pipeline->textbin == NULL) { MMPlayerGstElement* mainbin = NULL; - if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) { - LOGE("failed to create textbin. continuing without text\n"); + if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) { + LOGE("failed to create text sink bin. continuing without text\n"); goto ERROR; } @@ -5544,8 +5544,8 @@ static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player) pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink"); if (!pad) { - LOGE("failed to get video pad of textbin\n"); - return MM_ERROR_PLAYER_INTERNAL; + LOGE("failed to get sink pad of text queue"); + goto ERROR; } ghostpad = gst_ghost_pad_new("text_sink", pad); @@ -5558,6 +5558,7 @@ static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player) 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; } } @@ -5567,10 +5568,16 @@ static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player) 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_pipeline(mm_player_t* player) +static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player) { MMPlayerGstElement *textbin = NULL; GList *element_bucket = NULL; @@ -5656,6 +5663,9 @@ ERROR: 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 */ @@ -5666,8 +5676,9 @@ ERROR: if (!parent) { gst_object_unref(GST_OBJECT(textbin[i].gst)); textbin[i].gst = NULL; - } else + } else { gst_object_unref(GST_OBJECT(parent)); + } } } @@ -5675,8 +5686,7 @@ ERROR: if (textbin[MMPLAYER_T_BIN].gst) gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst)); - MMPLAYER_FREEIF(textbin); - + MMPLAYER_FREEIF(player->pipeline->textbin); player->pipeline->textbin = NULL; return MM_ERROR_PLAYER_INTERNAL; @@ -5684,9 +5694,10 @@ ERROR: static int -__mmplayer_gst_create_subtitle_src(mm_player_t* player) +__mmplayer_gst_create_text_pipeline(mm_player_t* player) { MMPlayerGstElement* mainbin = NULL; + MMPlayerGstElement* textbin = NULL; MMHandleType attrs = 0; GstElement *subsrc = NULL; GstElement *subparse = NULL; @@ -5697,7 +5708,9 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) MMPLAYER_FENTER(); /* get mainbin */ - MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED); + MMPLAYER_RETURN_VAL_IF_FAIL(player && + player->pipeline && + player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED); mainbin = player->pipeline->mainbin; @@ -5733,6 +5746,9 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc)) { LOGW("failed to add queue\n"); + gst_object_unref(mainbin[MMPLAYER_M_SUBSRC].gst); + mainbin[MMPLAYER_M_SUBSRC].gst = NULL; + mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_NUM; goto ERROR; } @@ -5754,6 +5770,9 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse)) { LOGW("failed to add subparse\n"); + gst_object_unref(mainbin[MMPLAYER_M_SUBPARSE].gst); + mainbin[MMPLAYER_M_SUBPARSE].gst = NULL; + mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_NUM; goto ERROR; } @@ -5768,13 +5787,23 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) LOGD("play subtitle using subtitle file\n"); if (player->pipeline->textbin == NULL) { - if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) { - LOGE("failed to create textbin. continuing without text\n"); + if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) { + LOGE("failed to create text sink bin. continuing without text\n"); goto ERROR; } - if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst))) { + textbin = player->pipeline->textbin; + + if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(textbin[MMPLAYER_T_BIN].gst))) { LOGW("failed to add textbin\n"); + + /* release signal */ + __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN); + + /* release textbin with it's childs */ + gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst)); + MMPLAYER_FREEIF(player->pipeline->textbin); + player->pipeline->textbin = textbin = NULL; goto ERROR; } @@ -5784,20 +5813,20 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) player->external_text_idx = 0; LOGI("player->textsink_linked set to 1\n"); } else { + textbin = player->pipeline->textbin; LOGD("text bin has been created. reuse it."); player->external_text_idx = 1; } - if (!gst_element_link_pads(subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink")) { + if (!gst_element_link_pads(subparse, "src", textbin[MMPLAYER_T_BIN].gst, "text_sink")) { LOGW("failed to link subparse and textbin\n"); goto ERROR; } - pad = gst_element_get_static_pad(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink"); - + pad = gst_element_get_static_pad(textbin[MMPLAYER_T_FAKE_SINK].gst, "sink"); if (!pad) { LOGE("failed to get sink pad from textsink to probe data"); - return MM_ERROR_PLAYER_INTERNAL; + goto ERROR; } gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, @@ -5813,7 +5842,26 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) return MM_ERROR_NONE; ERROR: + /* release text pipeline resource */ player->textsink_linked = 0; + + /* release signal */ + __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN); + + if (player->pipeline->textbin) { + LOGE("remove textbin"); + + /* release textbin with it's childs */ + MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN); + MMPLAYER_FREEIF(player->pipeline->textbin); + player->pipeline->textbin = NULL; + + } + + /* release subtitle elem */ + MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC); + MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE); + return MM_ERROR_PLAYER_INTERNAL; } @@ -6818,8 +6866,8 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */ if (__mmplayer_check_subtitle(player)) { - if (MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player)) - LOGE("fail to create subtitle src\n"); + if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) + LOGE("fail to create text pipeline"); } /* set sync handler to get tag synchronously */ @@ -14117,13 +14165,10 @@ int _mmplayer_sync_subtitle_pipeline(mm_player_t* player) MMPLAYER_FENTER(); /* check player handle */ - MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED); - - if (!(player->pipeline->mainbin) || !(player->pipeline->textbin)) { - LOGE("Pipeline is not in proper state\n"); - result = MM_ERROR_PLAYER_NOT_INITIALIZED; - goto EXIT; - } + MMPLAYER_RETURN_VAL_IF_FAIL(player && + player->pipeline && + player->pipeline->mainbin && + player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED); mainbin = player->pipeline->mainbin; textbin = player->pipeline->textbin; @@ -14147,8 +14192,11 @@ int _mmplayer_sync_subtitle_pipeline(mm_player_t* player) gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED); ret = gst_element_get_state(mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND); - if (GST_STATE_CHANGE_FAILURE == ret) + if (GST_STATE_CHANGE_FAILURE == ret) { LOGE("fail to state change.\n"); + result = MM_ERROR_PLAYER_INTERNAL; + goto ERROR; + } } gst_element_set_base_time(textbin[MMPLAYER_T_BIN].gst, base_time); @@ -14163,7 +14211,7 @@ int _mmplayer_sync_subtitle_pipeline(mm_player_t* player) if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) { result = MM_ERROR_PLAYER_INVALID_STATE; LOGE("gst_element_query_position failed, invalid state\n"); - goto EXIT; + goto ERROR; } LOGD("seek time = %lld, rate = %f\n", time, player->playback_rate); @@ -14172,16 +14220,33 @@ int _mmplayer_sync_subtitle_pipeline(mm_player_t* player) __gst_send_event_to_sink(player, event); } else { result = MM_ERROR_PLAYER_INTERNAL; - LOGE("gst_event_new_seek failed\n"); - goto EXIT; + LOGE("gst_event_new_seek failed"); /* pipeline will got error and can not be recovered */ + goto ERROR; } - // sync state with current pipeline + /* sync state with current pipeline */ gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst); gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst); gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst); -EXIT: + return MM_ERROR_NONE; + +ERROR: + /* release text pipeline resource */ + player->textsink_linked = 0; + + /* release signal */ + __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN); + + /* release textbin with it's childs */ + MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN); + MMPLAYER_FREEIF(player->pipeline->textbin); + player->pipeline->textbin = NULL; + + /* release subtitle elem */ + MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC); + MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE); + return result; } @@ -14202,15 +14267,12 @@ __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* fi MMPLAYER_FENTER(); /* check player handle */ - MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + MMPLAYER_RETURN_VAL_IF_FAIL(player && + player->pipeline && + player->pipeline->mainbin && + player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED); MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT); - if (!(player->pipeline) || !(player->pipeline->mainbin)) { - result = MM_ERROR_PLAYER_INVALID_STATE; - LOGE("Pipeline is not in proper state\n"); - goto EXIT; - } - mainbin = player->pipeline->mainbin; textbin = player->pipeline->textbin; @@ -14305,32 +14367,33 @@ int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filep /* check player handle */ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT); if (!player->pipeline) { // IDLE state mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath); if (mmf_attrs_commit(player->attrs)) { - LOGE("failed to commit.\n"); - result = MM_ERROR_PLAYER_INTERNAL; + LOGE("failed to commit"); /* subtitle path will not be created */ + return MM_ERROR_PLAYER_INTERNAL; } } else { // cur state <> IDLE(READY, PAUSE, PLAYING..) - if (filepath == NULL) - return MM_ERROR_COMMON_INVALID_ARGUMENT; - if (!__mmplayer_check_subtitle(player)) { mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath); if (mmf_attrs_commit(player->attrs)) { - LOGE("failed to commit.\n"); - result = MM_ERROR_PLAYER_INTERNAL; + LOGE("failed to commit"); + return MM_ERROR_PLAYER_INTERNAL; } - if (MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player)) - LOGE("fail to create subtitle src\n"); + if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) { + LOGE("fail to create text pipeline"); + return MM_ERROR_PLAYER_INTERNAL; + } result = _mmplayer_sync_subtitle_pipeline(player); - } else + } else { result = __mmplayer_change_external_subtitle_language(player, filepath); + } player->is_external_subtitle_added_now = TRUE; } -- 2.7.4