[0.6.266] release video resource
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.c
index 73046be..b936df4 100644 (file)
@@ -1144,13 +1144,13 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name)
        fakesink = gst_element_factory_make("fakesink", NULL);
        if (fakesink == NULL) {
                LOGE("failed to create fakesink");
-               goto EXIT;
+               return;
        }
 
-       /* store it as it's sink element */
-       __mmplayer_add_sink(player, fakesink, FALSE);
-
-       gst_bin_add(GST_BIN(pipeline), fakesink);
+       if (!gst_bin_add(GST_BIN(pipeline), fakesink)) {
+               LOGE("failed to add fakesink to pipeline");
+               goto ERROR;
+       }
 
        /* link */
        sinkpad = gst_element_get_static_pad(fakesink, "sink");
@@ -1159,8 +1159,7 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name)
 
        if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
                LOGE("failed to link fakesink");
-               gst_object_unref(GST_OBJECT(fakesink));
-               goto EXIT;
+               goto ERROR;
        }
 
        if (strstr(name, "video")) {
@@ -1175,12 +1174,28 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name)
        g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
        gst_element_set_state(fakesink, GST_STATE_PAUSED);
 
-EXIT:
+       /* store it as it's sink element */
+       __mmplayer_add_sink(player, fakesink, FALSE);
+
        if (sinkpad)
                gst_object_unref(GST_OBJECT(sinkpad));
 
        MMPLAYER_FLEAVE();
        return;
+
+ERROR:
+
+       if (sinkpad)
+               gst_object_unref(GST_OBJECT(sinkpad));
+
+       if (fakesink) {
+               gst_element_set_state(fakesink, GST_STATE_NULL);
+
+               if (!gst_bin_remove(GST_BIN(pipeline), fakesink))
+                       gst_object_unref(GST_OBJECT(fakesink));
+       }
+
+       return;
 }
 
 static GstElement *
@@ -1198,16 +1213,21 @@ __mmplayer_gst_make_concat(mmplayer_t *player, main_element_id_e elem_idx)
                return NULL;
        }
 
+       gst_element_set_state(concat, GST_STATE_PAUSED);
+
+       pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
+       if (!gst_bin_add(GST_BIN(pipeline), concat)) {
+               LOGE("failed to add concat to pipeline");
+               gst_element_set_state(concat, GST_STATE_NULL);
+               gst_object_unref(GST_OBJECT(concat));
+               return NULL;
+       }
+
        LOGD("Create concat [%d] element", elem_idx);
 
        player->pipeline->mainbin[elem_idx].id = elem_idx;
        player->pipeline->mainbin[elem_idx].gst = concat;
 
-       gst_element_set_state(concat, GST_STATE_PAUSED);
-
-       pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
-       gst_bin_add(GST_BIN(pipeline), concat);
-
        MMPLAYER_FLEAVE();
        return concat;
 }
@@ -1229,11 +1249,6 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp
        }
        g_object_set(selector, "sync-streams", TRUE, NULL);
 
-       player->pipeline->mainbin[elem_idx].id = elem_idx;
-       player->pipeline->mainbin[elem_idx].gst = selector;
-
-       /* player->track[stream_type].active_track_index = DEFAULT_TRACK; */
-
        srcpad = gst_element_get_static_pad(selector, "src");
 
        LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
@@ -1245,10 +1260,29 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp
        gst_element_set_state(selector, GST_STATE_PAUSED);
 
        pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
-       gst_bin_add(GST_BIN(pipeline), selector);
+       if (!gst_bin_add(GST_BIN(pipeline), selector)) {
+               LOGE("failed to add selector to pipeline");
+
+               if (player->track[stream_type].block_id != 0)
+                 gst_pad_remove_probe (srcpad, player->track[stream_type].block_id);
+               player->track[stream_type].block_id = 0;
+
+               if (player->track[stream_type].event_probe_id != 0)
+                 gst_pad_remove_probe (srcpad, player->track[stream_type].event_probe_id);
+               player->track[stream_type].event_probe_id = 0;
+
+               gst_object_unref(GST_OBJECT(srcpad));
+
+               gst_element_set_state(selector, GST_STATE_NULL);
+               gst_object_unref(GST_OBJECT(selector));
+               return NULL;
+       }
 
        gst_object_unref(GST_OBJECT(srcpad));
 
+       player->pipeline->mainbin[elem_idx].id = elem_idx;
+       player->pipeline->mainbin[elem_idx].gst = selector;
+
        MMPLAYER_FLEAVE();
        return selector;
 }
@@ -1415,6 +1449,7 @@ ERROR:
                sinkpad = NULL;
        }
 
+       MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pad-added");
        return;
 }
 
@@ -2086,7 +2121,10 @@ static void __mmplayer_video_param_set_display_overlay_sync_ui(mmplayer_t *playe
        /* common case if using overlay surface */
        mm_attrs_get_string_by_name(attrs, "exported_shell_handle", &handle);
        MMPLAYER_RETURN_IF_FAIL(handle);
-       g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "exported-shell-handle", handle, NULL);
+
+       gst_video_overlay_set_wl_window_exported_shell_handle(
+                       GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+                       handle);
        LOGD("set video param: exported_shell_handle (%s)", handle);
 }
 
@@ -2121,13 +2159,6 @@ _mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name)
 
        MMPLAYER_FENTER();
 
-       mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &curr_type);
-
-       if (curr_type != MM_DISPLAY_SURFACE_OVERLAY && curr_type != MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) {
-               LOGE("current type(%d) is wrong", curr_type);
-               return MM_ERROR_PLAYER_INTERNAL;
-       }
-
        if (!player || !player->pipeline || !player->pipeline->mainbin || !player->pipeline->videobin ||
                !player->pipeline->videobin[MMPLAYER_V_BIN].gst ||
                !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
@@ -2135,6 +2166,13 @@ _mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name)
                return MM_ERROR_PLAYER_NOT_INITIALIZED;
        }
 
+       mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &curr_type);
+
+       if (curr_type != MM_DISPLAY_SURFACE_OVERLAY && curr_type != MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) {
+               LOGE("current type(%d) is wrong", curr_type);
+               return MM_ERROR_PLAYER_INTERNAL;
+       }
+
        if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
                LOGE("invalid videosink [%s]", player->ini.videosink_element_overlay);
                return MM_ERROR_PLAYER_INTERNAL;
@@ -2232,6 +2270,8 @@ _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
                                                                        player->pipeline->videobin[MMPLAYER_V_SINK].gst,
                                                                        MM_ERROR_PLAYER_NO_OP); /* invalid op */
 
+               __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
+
                __mmplayer_switch_stream(player, MM_PLAYER_TRACK_TYPE_VIDEO, INVALID_TRACK_INDEX);
 
                /* release decoder resource */
@@ -6308,8 +6348,10 @@ ERROR:
                /* And, it still has a parent "player".
                 * You need to let the parent manage the object instead of unreffing the object directly.
                 */
-               gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
-               gst_object_unref(queue2);
+               if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
+                       LOGE("failed to remove queue2");
+                       gst_object_unref(queue2);
+               }
                queue2 = NULL;
        }
 
@@ -6324,8 +6366,10 @@ ERROR:
                 * You need to let the parent manage the object instead of unreffing the object directly.
                 */
 
-               gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
-               gst_object_unref(decodebin);
+               if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
+                       LOGE("failed to remove decodebin");
+                       gst_object_unref(decodebin);
+               }
                decodebin = NULL;
        }
 
@@ -6741,7 +6785,11 @@ __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type)
                g_ptr_array_set_size(selector->streams, 0);
 
                gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
-               gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
+               if (!gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst),
+                                                       player->pipeline->mainbin[selectorId].gst)) {
+                       LOGE("failed to remove selector");
+                       gst_object_unref(player->pipeline->mainbin[selectorId].gst);
+               }
 
                player->pipeline->mainbin[selectorId].gst = NULL;
                selector = NULL;
@@ -7552,31 +7600,36 @@ _mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *pad,
 
        __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
 
-       if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), videobin[MMPLAYER_V_BIN].gst)) {
-               LOGE("failed to remove videobin");
+       __mmplayer_del_sink(player, videobin[MMPLAYER_V_SINK].gst);
+
+       LOGD("remove videobin");
+       ret = _mmplayer_gst_set_state(player, videobin[MMPLAYER_V_BIN].gst,
+                               GST_STATE_NULL, FALSE, timeout);
+       if (ret != MM_ERROR_NONE) {
+               LOGE("fail to change state of videobin to NULL");
+               return;
        }
 
-       if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_V_CONCAT].gst)) {
-               LOGE("failed to remove video concat");
+       if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), videobin[MMPLAYER_V_BIN].gst)) {
+               LOGE("failed to remove videobin");
+               gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
        }
 
-       ret = _mmplayer_gst_set_state(player, videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL, FALSE, timeout);
+       LOGD("remove concat");
+       ret = _mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_V_CONCAT].gst,
+                               GST_STATE_NULL, FALSE, timeout);
        if (ret != MM_ERROR_NONE) {
-               LOGE("fail to change state to NULL");
+               LOGE("fail to change state of concat to NULL");
                return;
        }
 
-       ret = _mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_V_CONCAT].gst, GST_STATE_NULL, FALSE, timeout);
-       if (ret != MM_ERROR_NONE) {
-               LOGE("fail to change state to NULL");
-               return;
+       if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_V_CONCAT].gst)) {
+               LOGE("failed to remove video concat");
+               gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_V_CONCAT].gst));
        }
 
-       gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_V_CONCAT].gst));
        mainbin[MMPLAYER_M_V_CONCAT].gst = NULL;
        mainbin[MMPLAYER_M_V_CONCAT].id = 0;
-
-       gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
        MMPLAYER_FREEIF(player->pipeline->videobin);
 
        ret = __mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY);
@@ -7705,75 +7758,75 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
        if (__mmplayer_add_dump_buffer_probe(player, element))
                LOGD("add buffer probe");
 
-       if (g_strrstr(klass, "Codec/Decoder/Audio")) {
-               gchar *selected = NULL;
-               selected = g_strdup(GST_ELEMENT_NAME(element));
-               player->audio_decoders = g_list_append(player->audio_decoders, selected);
-
-               /* update codec info */
-               player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
-               player->can_support_codec |= FOUND_PLUGIN_AUDIO;
-               player->audiodec_linked = 1;
-       } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
-               /* update codec info */
-               player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
-               player->can_support_codec |= FOUND_PLUGIN_VIDEO;
-               player->videodec_linked = 1;
-       }
-
-       if (g_strrstr(klass, "Demuxer/Adaptive")) {
-               player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
-               player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element;
+       if (g_strrstr(klass, "Decoder")) {
+               if (g_strrstr(klass, "Audio")) {
+                       player->audio_decoders = g_list_append(player->audio_decoders,
+                                                                                                                                       g_strdup(GST_ELEMENT_NAME(element)));
 
-               LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth,
-                                               player->adaptive_info.limit.width, player->adaptive_info.limit.height);
+                       /* update codec info */
+                       player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
+                       player->can_support_codec |= FOUND_PLUGIN_AUDIO;
+                       player->audiodec_linked = 1;
+               } else if (g_strrstr(klass, "Video")) {
+                       GstElement *video_parse = player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst;
+                       /* update codec info */
+                       player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
+                       player->can_support_codec |= FOUND_PLUGIN_VIDEO;
+                       player->videodec_linked = 1;
+
+                       if (video_parse) {
+                               GstPad *srcpad = gst_element_get_static_pad (video_parse, "src");
+                               if (srcpad) {
+                                       GstCaps *caps = NULL;
+                                       GstStructure *str = NULL;
+                                       const gchar *name = NULL;
+                                       gboolean caps_ret = TRUE;
+
+                                       MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD (srcpad, caps, str, name, caps_ret);
+                                       if (caps_ret && str) {
+                                               const gchar *stream_format = gst_structure_get_string (str, "stream-format");
+                                               if (stream_format && g_strrstr(stream_format, "byte-stream")) {
+                                                       if ((g_object_class_find_property(G_OBJECT_GET_CLASS(video_parse), "config-interval"))) {
+                                                               g_object_set(G_OBJECT(video_parse), "config-interval", -1, NULL);
+                                                               LOGD("Send SPS and PPS Insertion every IDR frame");
+                                                       }
+                                               }
+                                       }
+                                       gst_object_unref(GST_OBJECT(srcpad));
+                               }
+                       }
+               }
+       } else if (g_strrstr(klass, "Demuxer")) {
+               if (g_strrstr(klass, "Adaptive")) {
+                       player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
+                       player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element;
 
-               g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
-                                               "max-bandwidth", player->adaptive_info.limit.bandwidth,
-                                               "max-video-width", player->adaptive_info.limit.width,
-                                               "max-video-height", player->adaptive_info.limit.height, NULL);
+                       LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth,
+                                                       player->adaptive_info.limit.width, player->adaptive_info.limit.height);
 
-       } else if (g_strrstr(klass, "Demuxer")) {
+                       g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
+                                                       "max-bandwidth", player->adaptive_info.limit.bandwidth,
+                                                       "max-video-width", player->adaptive_info.limit.width,
+                                                       "max-video-height", player->adaptive_info.limit.height, NULL);
+               } else {
 #ifdef __DEBUG__
-               LOGD("plugged element is demuxer. take it");
+                       LOGD("plugged element is demuxer. take it");
 #endif
-               player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
-               player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
+                       player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
+                       player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
+               }
        } else if (g_strrstr(klass, "Parser") && (g_strrstr(klass, "Video"))) {
                player->pipeline->mainbin[MMPLAYER_M_V_PARSE].id = MMPLAYER_M_V_PARSE;
                player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst = element;
        }
 
-       if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
-               int surface_type = 0;
-
-               mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
-       }
-
-       // to support trust-zone only
-       if (g_strrstr(factory_name, "asfdemux")) {
-               LOGD("set file-location %s", player->profile.uri);
-               g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL);
-       } else if (g_strrstr(factory_name, "legacyh264parse")) {
-               LOGD("[%s] output-format to legacyh264parse", "mssdemux");
-               g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
-       } else if (g_strrstr(factory_name, "mpegaudioparse")) {
+       if (g_strrstr(factory_name, "mpegaudioparse")) {
                if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
                        (__mmplayer_is_only_mp3_type(player->type))) {
                        LOGD("[mpegaudioparse] set streaming pull mode.");
                        g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
                }
-       } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
-               player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
-       } else if (g_strrstr(factory_name, "omxdec_h264")) {
-               GstElement *video_parse = player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst;
-               if (video_parse && (g_object_class_find_property(G_OBJECT_GET_CLASS(video_parse), "config-interval"))) {
-                       g_object_set(G_OBJECT(video_parse), "config-interval", -1, NULL);
-                       LOGD("Send SPS and PPS Insertion every IDR frame");
-               }
-       }
-
-       if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
+       } else if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
                (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
                LOGD("plugged element is multiqueue. take it %s", GST_ELEMENT_NAME(element));
 
@@ -7787,7 +7840,6 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
                        _mm_player_streaming_set_multiqueue(player->streamer, element);
                        _mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
                }
-
        }
 
        return;
@@ -8491,6 +8543,24 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind
                g_list_free(streams);
        }
 
+       /* in paused state, seek to current pos to flush mq buffer and release waiting task */
+       if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
+               gint64 pos_nsec = GST_CLOCK_TIME_NONE;
+
+               if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
+                       pos_nsec = player->last_position;
+
+               LOGD("current pos %" GST_TIME_FORMAT ", rate = %f", GST_TIME_ARGS(pos_nsec), player->playback_rate);
+
+               if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
+                                       player->playback_rate, GST_FORMAT_TIME,
+                                       (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
+                                       GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE)) {
+                       LOGW("failed to seek");
+                       return MM_ERROR_PLAYER_INTERNAL;
+               }
+       }
+
        MMPLAYER_FLEAVE();
        return MM_ERROR_NONE;
 }