Destroy gstreamer transcoding pipelines properly so the input and output files are closed, and can be read again on Windows.
This commit is contained in:
parent
a00d7e1738
commit
91b4cfcb68
@ -401,17 +401,16 @@ bool Transcoder::StartJob(const Job &job) {
|
|||||||
// Create the pipeline.
|
// Create the pipeline.
|
||||||
// This should be a scoped_ptr, but scoped_ptr doesn't support custom
|
// This should be a scoped_ptr, but scoped_ptr doesn't support custom
|
||||||
// destructors.
|
// destructors.
|
||||||
state->pipeline_.reset(gst_pipeline_new("pipeline"),
|
state->pipeline_ = gst_pipeline_new("pipeline");
|
||||||
boost::bind(gst_object_unref, _1));
|
|
||||||
if (!state->pipeline_) return false;
|
if (!state->pipeline_) return false;
|
||||||
|
|
||||||
// Create all the elements
|
// Create all the elements
|
||||||
GstElement* src = CreateElement("filesrc", state->pipeline_.get());
|
GstElement* src = CreateElement("filesrc", state->pipeline_);
|
||||||
GstElement* decode = CreateElement("decodebin2", state->pipeline_.get());
|
GstElement* decode = CreateElement("decodebin2", state->pipeline_);
|
||||||
GstElement* convert = CreateElement("audioconvert", state->pipeline_.get());
|
GstElement* convert = CreateElement("audioconvert", state->pipeline_);
|
||||||
GstElement* codec = CreateElementForMimeType("Codec/Encoder/Audio", job.preset.codec_mimetype_, state->pipeline_.get());
|
GstElement* codec = CreateElementForMimeType("Codec/Encoder/Audio", job.preset.codec_mimetype_, state->pipeline_);
|
||||||
GstElement* muxer = CreateElementForMimeType("Codec/Muxer", job.preset.muxer_mimetype_, state->pipeline_.get());
|
GstElement* muxer = CreateElementForMimeType("Codec/Muxer", job.preset.muxer_mimetype_, state->pipeline_);
|
||||||
GstElement* sink = CreateElement("filesink", state->pipeline_.get());
|
GstElement* sink = CreateElement("filesink", state->pipeline_);
|
||||||
|
|
||||||
if (!src || !decode || !convert || !sink)
|
if (!src || !decode || !convert || !sink)
|
||||||
return false;
|
return false;
|
||||||
@ -445,11 +444,11 @@ bool Transcoder::StartJob(const Job &job) {
|
|||||||
state->convert_element_ = convert;
|
state->convert_element_ = convert;
|
||||||
|
|
||||||
g_signal_connect(decode, "new-decoded-pad", G_CALLBACK(NewPadCallback), state.get());
|
g_signal_connect(decode, "new-decoded-pad", G_CALLBACK(NewPadCallback), state.get());
|
||||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(state->pipeline_.get())), BusCallbackSync, state.get());
|
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(state->pipeline_)), BusCallbackSync, state.get());
|
||||||
state->bus_callback_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(state->pipeline_.get())), BusCallback, state.get());
|
state->bus_callback_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(state->pipeline_)), BusCallback, state.get());
|
||||||
|
|
||||||
// Start the pipeline
|
// Start the pipeline
|
||||||
gst_element_set_state(state->pipeline_.get(), GST_STATE_PLAYING);
|
gst_element_set_state(state->pipeline_, GST_STATE_PLAYING);
|
||||||
|
|
||||||
// GStreamer now transcodes in another thread, so we can return now and do
|
// GStreamer now transcodes in another thread, so we can return now and do
|
||||||
// something else. Keep the JobState object around. It'll post an event
|
// something else. Keep the JobState object around. It'll post an event
|
||||||
@ -459,6 +458,13 @@ bool Transcoder::StartJob(const Job &job) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transcoder::JobState::~JobState() {
|
||||||
|
if (pipeline_) {
|
||||||
|
gst_element_set_state(pipeline_, GST_STATE_NULL);
|
||||||
|
gst_object_unref(pipeline_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Transcoder::event(QEvent* e) {
|
bool Transcoder::event(QEvent* e) {
|
||||||
if (e->type() == JobFinishedEvent::sEventType) {
|
if (e->type() == JobFinishedEvent::sEventType) {
|
||||||
JobFinishedEvent* finished_event = static_cast<JobFinishedEvent*>(e);
|
JobFinishedEvent* finished_event = static_cast<JobFinishedEvent*>(e);
|
||||||
@ -481,7 +487,7 @@ bool Transcoder::event(QEvent* e) {
|
|||||||
// Remove event handlers from the gstreamer pipeline so they don't get
|
// Remove event handlers from the gstreamer pipeline so they don't get
|
||||||
// called after the pipeline is shutting down
|
// called after the pipeline is shutting down
|
||||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(
|
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(
|
||||||
finished_event->state_->pipeline_.get())), NULL, NULL);
|
finished_event->state_->pipeline_)), NULL, NULL);
|
||||||
g_source_remove(finished_event->state_->bus_callback_id_);
|
g_source_remove(finished_event->state_->bus_callback_id_);
|
||||||
|
|
||||||
// Remove it from the list - this will also destroy the GStreamer pipeline
|
// Remove it from the list - this will also destroy the GStreamer pipeline
|
||||||
@ -510,14 +516,14 @@ void Transcoder::Cancel() {
|
|||||||
|
|
||||||
// Remove event handlers from the gstreamer pipeline so they don't get
|
// Remove event handlers from the gstreamer pipeline so they don't get
|
||||||
// called after the pipeline is shutting down
|
// called after the pipeline is shutting down
|
||||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(
|
gst_bus_set_sync_handler(gst_pipeline_get_bus(
|
||||||
state->pipeline_.get())), NULL, NULL);
|
GST_PIPELINE(state->pipeline_)), NULL, NULL);
|
||||||
g_source_remove(state->bus_callback_id_);
|
g_source_remove(state->bus_callback_id_);
|
||||||
|
|
||||||
// Stop the pipeline
|
// Stop the pipeline
|
||||||
if (gst_element_set_state(state->pipeline_.get(), GST_STATE_NULL) == GST_STATE_CHANGE_ASYNC) {
|
if (gst_element_set_state(state->pipeline_, GST_STATE_NULL) == GST_STATE_CHANGE_ASYNC) {
|
||||||
// Wait for it to finish stopping...
|
// Wait for it to finish stopping...
|
||||||
gst_element_get_state(state->pipeline_.get(), NULL, NULL, GST_CLOCK_TIME_NONE);
|
gst_element_get_state(state->pipeline_, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the job, this destroys the GStreamer pipeline too
|
// Remove the job, this destroys the GStreamer pipeline too
|
||||||
@ -536,8 +542,8 @@ QMap<QString, float> Transcoder::GetProgress() const {
|
|||||||
gint64 duration = 0;
|
gint64 duration = 0;
|
||||||
GstFormat format = GST_FORMAT_TIME;
|
GstFormat format = GST_FORMAT_TIME;
|
||||||
|
|
||||||
gst_element_query_position(state->pipeline_.get(), &format, &position);
|
gst_element_query_position(state->pipeline_, &format, &position);
|
||||||
gst_element_query_duration(state->pipeline_.get(), &format, &duration);
|
gst_element_query_duration(state->pipeline_, &format, &duration);
|
||||||
|
|
||||||
ret[state->job_.input] = float(position) / duration;
|
ret[state->job_.input] = float(position) / duration;
|
||||||
}
|
}
|
||||||
|
@ -91,14 +91,16 @@ class Transcoder : public QObject {
|
|||||||
// job's thread.
|
// job's thread.
|
||||||
struct JobState {
|
struct JobState {
|
||||||
JobState(const Job& job, Transcoder* parent)
|
JobState(const Job& job, Transcoder* parent)
|
||||||
: job_(job), parent_(parent), convert_element_(NULL), bus_callback_id_(0) {}
|
: job_(job), parent_(parent), pipeline_(NULL), convert_element_(NULL),
|
||||||
|
bus_callback_id_(0) {}
|
||||||
|
~JobState();
|
||||||
|
|
||||||
void PostFinished(bool success);
|
void PostFinished(bool success);
|
||||||
void ReportError(GstMessage* msg);
|
void ReportError(GstMessage* msg);
|
||||||
|
|
||||||
Job job_;
|
Job job_;
|
||||||
Transcoder* parent_;
|
Transcoder* parent_;
|
||||||
boost::shared_ptr<GstElement> pipeline_;
|
GstElement* pipeline_;
|
||||||
GstElement* convert_element_;
|
GstElement* convert_element_;
|
||||||
int bus_callback_id_;
|
int bus_callback_id_;
|
||||||
};
|
};
|
||||||
|
@ -1070,14 +1070,14 @@ msgid ""
|
|||||||
"required GStreamer plugins installed"
|
"required GStreamer plugins installed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: transcoder/transcoder.cpp:426
|
#: transcoder/transcoder.cpp:425
|
||||||
#, qt-format
|
#, qt-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Couldn't find a muxer for %1, check you have the correct GStreamer plugins "
|
"Couldn't find a muxer for %1, check you have the correct GStreamer plugins "
|
||||||
"installed"
|
"installed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: transcoder/transcoder.cpp:420
|
#: transcoder/transcoder.cpp:419
|
||||||
#, qt-format
|
#, qt-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Couldn't find an encoder for %1, check you have the correct GStreamer "
|
"Couldn't find an encoder for %1, check you have the correct GStreamer "
|
||||||
|
Loading…
x
Reference in New Issue
Block a user