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);
}