[0.6.52] add subtitle error handling 93/132193/1
authorEunhae Choi <eunhae1.choi@samsung.com>
Thu, 1 Jun 2017 11:32:11 +0000 (20:32 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Thu, 1 Jun 2017 11:32:14 +0000 (20:32 +0900)
- make right error return
- release resource in case of subtitle error
  to main pipeline make work

Change-Id: I7c0c1bb6c172d807a82cca0b122d9aedf69d9551

packaging/libmm-player.spec
src/mm_player_priv.c

index a1ea7fe..89785bc 100644 (file)
@@ -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
index a79d4ff..a01e72d 100644 (file)
 /*---------------------------------------------------------------------------
 |    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;
        }