C++11 如何重用GStreamer播放器来运行视频队列? 我有一个C++ GSPER播放器实现,它运行一个本地视频作为参数发送给我的函数“PraveSimulink”。因此,我需要运行一系列视频,但我希望重用当前播放器来执行此操作,以避免不必要的内存分配。我做的播放器仍然活着,但当一个新的视频播放,一个新的分配是作出了一段时间后,我的应用程序崩溃的内存泄漏。如何避免这种情况?我可以使用相同的GStreamer播放器吗?我做错了什么

C++11 如何重用GStreamer播放器来运行视频队列? 我有一个C++ GSPER播放器实现,它运行一个本地视频作为参数发送给我的函数“PraveSimulink”。因此,我需要运行一系列视频,但我希望重用当前播放器来执行此操作,以避免不必要的内存分配。我做的播放器仍然活着,但当一个新的视频播放,一个新的分配是作出了一段时间后,我的应用程序崩溃的内存泄漏。如何避免这种情况?我可以使用相同的GStreamer播放器吗?我做错了什么,c++11,video,gstreamer,C++11,Video,Gstreamer,谢谢 /** * Executes a specific Video in GStreamer Player. * * Will starts a video execution into GStreamer Video Player and emits the signal to * GlossVideoManager when this current execution was ended. * * @param path The video path to be played

谢谢

/**
 * Executes a specific Video in GStreamer Player.
 *
 * Will starts a video execution into GStreamer Video Player and emits the signal to
 * GlossVideoManager when this current execution was ended.
 *
 * @param path The video path to be played.
 */
void PlayerImpl::mPlayerSimulation(const std::string& path) {

    bool terminate = false;

    /* Set the URI to play */
    std::string gsPath = gst_filename_to_uri(path.c_str(), nullptr);
    g_object_set(mGstPlayer.source, "uri", gsPath.c_str(), NULL);

    /* Start playing */
    mRet = gst_element_set_state(mGstPlayer.pipeline, GST_STATE_PLAYING);
    if (mRet == GST_STATE_CHANGE_FAILURE) {
        pil::Logger::error("Unable to set the pipeline to the playing state.");
        gst_object_unref(mGstPlayer.pipeline);
        return;
    }

    /* Listen to the bus */
    mBus = gst_element_get_bus(mGstPlayer.pipeline);
    do {
        mMsg = gst_bus_timed_pop_filtered(mBus, GST_CLOCK_TIME_NONE,
            GstMessageType(GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS));

        /* Parse message */
        if (mMsg != nullptr) {
            GError* err;
            gchar* debug_info;

            switch (GST_MESSAGE_TYPE(mMsg)) {
            case GST_MESSAGE_ERROR:
                gst_message_parse_error(mMsg, &err, &debug_info);
                pil::Logger::error("Error received from element "
                    + std::string(GST_OBJECT_NAME(mMsg->src)) + ": " + err->message);
                pil::Logger::debug("Debugging information: " + std::string(debug_info));
                g_clear_error(&err);
                g_free(debug_info);
                terminate = true;
                break;
            case GST_MESSAGE_EOS:
                pil::Logger::debug("End-Of-Stream reached.");
                terminate = true;
                break;
            case GST_MESSAGE_STATE_CHANGED:
                /* We are only interested in state-changed messages from the pipeline */
                if (GST_MESSAGE_SRC(mMsg) == GST_OBJECT(mGstPlayer.pipeline)) {
                    GstState old_state, new_state, pending_state;
                    gst_message_parse_state_changed(mMsg, &old_state, &new_state, &pending_state);
                    pil::Logger::debug("Pipeline state changed from "
                        + std::string(gst_element_state_get_name(old_state)) + " to "
                        + std::string(gst_element_state_get_name(new_state)));
                }
                break;
            default:
                /* We should not reach here */
                pil::Logger::error("Unexpected message received.");
                break;
            }
            gst_message_unref(mMsg);
        }
    } while (!terminate);

    /* Free resources */
    gst_object_unref(mBus);
    gst_element_set_state(mGstPlayer.pipeline, GST_STATE_READY);

    Logger::debug(path.substr(29));

    this->mPaused = (path.find("POSE_NEUTRA") != std::string::npos);
    this->onPlayerReady();
}


/**
 * Receives a video path to be played.
 *
 * Receives a video path that will be consumed by the video player.
 *
 * @param path The video path to be played.
 *
 */
void PlayerImpl::playVideo(const std::string& path) {
boost::thread reader(&PlayerImpl::mPlayerSimulation, this, path);
reader.detach();
}


/**
 * Starts the player.
 *
 * Initializes the video player, triggering the onReady signal.
 */
void PlayerImpl::start() {

    /* Initializing GStreamer */
    gst_init(nullptr, nullptr);

    /* Create the elements */
    mGstPlayer.source = gst_element_factory_make("uridecodebin", "source");
    mGstPlayer.convert = gst_element_factory_make("videoconvert", "convert");
    mGstPlayer.sink = gst_element_factory_make("autovideosink", "sink");

    /* Create the empty pipeline */
    mGstPlayer.pipeline = gst_pipeline_new("test-pipeline");

    if ((mGstPlayer.pipeline == nullptr) || (mGstPlayer.source == nullptr)
        || (mGstPlayer.convert == nullptr) || (mGstPlayer.sink == nullptr)) {
        pil::Logger::error("Not all elements could be created.");
        return;
    }

    /* Build the pipeline. Note that we are NOT linking the source at this
     * point. We will do it later. */
    gst_bin_add_many(
        GST_BIN(mGstPlayer.pipeline), mGstPlayer.source, mGstPlayer.convert, mGstPlayer.sink, NULL);
    if (gst_element_link(mGstPlayer.convert, mGstPlayer.sink) == 0) {
        pil::Logger::error("Elements could not be linked.");
        gst_object_unref(mGstPlayer.pipeline);
        return;
    }

    /* Connect to the pad-added signal */
    g_signal_connect(mGstPlayer.source, "pad-added", G_CALLBACK(padAddedHandler), &mGstPlayer);

    onPlayerReady();
}



/**
 * Stops the player.
 *
 * Finalizes the video player and free the GStreamer resources.
 */
void PlayerImpl::stop() {
    if (!this->mStopped) {
        this->mStopped = true;
        gst_element_set_state(mGstPlayer.pipeline, GST_STATE_NULL);
        gst_object_unref(mGstPlayer.pipeline);
    }
}



/* This function will be called by the pad-added signal */
static void padAddedHandler(GstElement* src, GstPad* newPad, GstPlayer* data) {
    GstPad* sinkPad = gst_element_get_static_pad(data->convert, "sink");
    GstPadLinkReturn ret;
    GstCaps* newPadCaps = nullptr;
    GstStructure* newPadStruct = nullptr;
    const gchar* newPadType = nullptr;

    pil::Logger::debug("Received new pad " + std::string(GST_PAD_NAME(newPad)) + " from "
        + GST_ELEMENT_NAME(src) + ":");

    /* If our converter is already linked, we have nothing to do here */
    if (gst_pad_is_linked(sinkPad) != 0) {
        pil::Logger::debug("  We are already linked. Ignoring.");
        goto exit;
    }

    /* Check the new pad's type */
    newPadCaps = gst_pad_query_caps(newPad, nullptr);
    newPadStruct = gst_caps_get_structure(newPadCaps, 0);
    newPadType = gst_structure_get_name(newPadStruct);
    if (g_str_has_prefix(newPadType, "video/x-raw") == 0) {
        pil::Logger::debug(
            "  It has type " + std::string(newPadType) + " which is not raw video. Ignoring.");
        goto exit;
    }

    /* Attempt the link */
    ret = gst_pad_link(newPad, sinkPad);
    if (GST_PAD_LINK_FAILED(ret)) {
        pil::Logger::debug("  Type is " + std::string(newPadType) + " but link failed.");
    } else {
        pil::Logger::debug("  Link succeeded (type " + std::string(newPadType) + ").");
    }

    exit:
    /* Unreference the new pad's caps, if we got them */
    if (newPadCaps != nullptr) {
        gst_caps_unref(newPadCaps);
    }

    /* Unreference the sink pad */
    gst_object_unref(sinkPad);
}