From 91b4cfcb68235e01df3ba39fdefe9994f347bb6e Mon Sep 17 00:00:00 2001 From: David Sansome Date: Tue, 29 Nov 2011 16:57:11 +0000 Subject: [PATCH] Destroy gstreamer transcoding pipelines properly so the input and output files are closed, and can be read again on Windows. --- src/transcoder/transcoder.cpp | 42 ++++++++++++++++++------------- src/transcoder/transcoder.h | 6 +++-- src/translations/translations.pot | 4 +-- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/transcoder/transcoder.cpp b/src/transcoder/transcoder.cpp index 2554d39da..677a8bc45 100644 --- a/src/transcoder/transcoder.cpp +++ b/src/transcoder/transcoder.cpp @@ -401,17 +401,16 @@ bool Transcoder::StartJob(const Job &job) { // Create the pipeline. // This should be a scoped_ptr, but scoped_ptr doesn't support custom // destructors. - state->pipeline_.reset(gst_pipeline_new("pipeline"), - boost::bind(gst_object_unref, _1)); + state->pipeline_ = gst_pipeline_new("pipeline"); if (!state->pipeline_) return false; // Create all the elements - GstElement* src = CreateElement("filesrc", state->pipeline_.get()); - GstElement* decode = CreateElement("decodebin2", state->pipeline_.get()); - GstElement* convert = CreateElement("audioconvert", state->pipeline_.get()); - GstElement* codec = CreateElementForMimeType("Codec/Encoder/Audio", job.preset.codec_mimetype_, state->pipeline_.get()); - GstElement* muxer = CreateElementForMimeType("Codec/Muxer", job.preset.muxer_mimetype_, state->pipeline_.get()); - GstElement* sink = CreateElement("filesink", state->pipeline_.get()); + GstElement* src = CreateElement("filesrc", state->pipeline_); + GstElement* decode = CreateElement("decodebin2", state->pipeline_); + GstElement* convert = CreateElement("audioconvert", state->pipeline_); + GstElement* codec = CreateElementForMimeType("Codec/Encoder/Audio", job.preset.codec_mimetype_, state->pipeline_); + GstElement* muxer = CreateElementForMimeType("Codec/Muxer", job.preset.muxer_mimetype_, state->pipeline_); + GstElement* sink = CreateElement("filesink", state->pipeline_); if (!src || !decode || !convert || !sink) return false; @@ -445,11 +444,11 @@ bool Transcoder::StartJob(const Job &job) { state->convert_element_ = convert; 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()); - state->bus_callback_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(state->pipeline_.get())), BusCallback, 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_)), BusCallback, state.get()); // 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 // something else. Keep the JobState object around. It'll post an event @@ -459,6 +458,13 @@ bool Transcoder::StartJob(const Job &job) { return true; } +Transcoder::JobState::~JobState() { + if (pipeline_) { + gst_element_set_state(pipeline_, GST_STATE_NULL); + gst_object_unref(pipeline_); + } +} + bool Transcoder::event(QEvent* e) { if (e->type() == JobFinishedEvent::sEventType) { JobFinishedEvent* finished_event = static_cast(e); @@ -481,7 +487,7 @@ bool Transcoder::event(QEvent* e) { // Remove event handlers from the gstreamer pipeline so they don't get // called after the pipeline is shutting down 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_); // 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 // called after the pipeline is shutting down - gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE( - state->pipeline_.get())), NULL, NULL); + gst_bus_set_sync_handler(gst_pipeline_get_bus( + GST_PIPELINE(state->pipeline_)), NULL, NULL); g_source_remove(state->bus_callback_id_); // 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... - 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 @@ -536,8 +542,8 @@ QMap Transcoder::GetProgress() const { gint64 duration = 0; GstFormat format = GST_FORMAT_TIME; - gst_element_query_position(state->pipeline_.get(), &format, &position); - gst_element_query_duration(state->pipeline_.get(), &format, &duration); + gst_element_query_position(state->pipeline_, &format, &position); + gst_element_query_duration(state->pipeline_, &format, &duration); ret[state->job_.input] = float(position) / duration; } diff --git a/src/transcoder/transcoder.h b/src/transcoder/transcoder.h index fbcb77bb7..58c53288e 100644 --- a/src/transcoder/transcoder.h +++ b/src/transcoder/transcoder.h @@ -91,14 +91,16 @@ class Transcoder : public QObject { // job's thread. struct JobState { 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 ReportError(GstMessage* msg); Job job_; Transcoder* parent_; - boost::shared_ptr pipeline_; + GstElement* pipeline_; GstElement* convert_element_; int bus_callback_id_; }; diff --git a/src/translations/translations.pot b/src/translations/translations.pot index 182f0b5a0..262cd651b 100644 --- a/src/translations/translations.pot +++ b/src/translations/translations.pot @@ -1070,14 +1070,14 @@ msgid "" "required GStreamer plugins installed" msgstr "" -#: transcoder/transcoder.cpp:426 +#: transcoder/transcoder.cpp:425 #, qt-format msgid "" "Couldn't find a muxer for %1, check you have the correct GStreamer plugins " "installed" msgstr "" -#: transcoder/transcoder.cpp:420 +#: transcoder/transcoder.cpp:419 #, qt-format msgid "" "Couldn't find an encoder for %1, check you have the correct GStreamer "