[Goodies-commits] r5830 - xfburn/trunk/xfburn
David Mohr
squisher at xfce.org
Mon Oct 27 02:18:12 CET 2008
Author: squisher
Date: 2008-10-27 01:18:12 +0000 (Mon, 27 Oct 2008)
New Revision: 5830
Modified:
xfburn/trunk/xfburn/xfburn-burn-audio-cd-composition-dialog.c
xfburn/trunk/xfburn/xfburn-transcoder-basic.c
xfburn/trunk/xfburn/xfburn-transcoder-gst.c
xfburn/trunk/xfburn/xfburn-transcoder.c
xfburn/trunk/xfburn/xfburn-transcoder.h
Log:
Improving transcoder infrastructure and gst support (still not 100% working)
Modified: xfburn/trunk/xfburn/xfburn-burn-audio-cd-composition-dialog.c
===================================================================
--- xfburn/trunk/xfburn/xfburn-burn-audio-cd-composition-dialog.c 2008-10-26 23:59:52 UTC (rev 5829)
+++ xfburn/trunk/xfburn/xfburn-burn-audio-cd-composition-dialog.c 2008-10-27 01:18:12 UTC (rev 5830)
@@ -544,10 +544,6 @@
track_list = g_slist_next (track_list);
}
- /*
- src_fifo = burn_fifo_source_new (src, 2048, xfburn_settings_get_int ("fifo-size", FIFO_DEFAULT_SIZE) / 2, 0);
- burn_source_free (src);
- */
if (!abort) {
if (!xfburn_transcoder_prepare (trans, &error)) {
xfburn_progress_dialog_burning_failed (XFBURN_PROGRESS_DIALOG (dialog_progress), error->message);
@@ -565,6 +561,8 @@
}
}
+ xfburn_transcoder_finish (trans);
+
for (j=0; j<i; j++) {
burn_track_free (tracks[j]);
}
Modified: xfburn/trunk/xfburn/xfburn-transcoder-basic.c
===================================================================
--- xfburn/trunk/xfburn/xfburn-transcoder-basic.c 2008-10-26 23:59:52 UTC (rev 5829)
+++ xfburn/trunk/xfburn/xfburn-transcoder-basic.c 2008-10-27 01:18:12 UTC (rev 5830)
@@ -187,7 +187,7 @@
if (stat (fn, &s) != 0) {
g_set_error (error, XFBURN_ERROR, XFBURN_ERROR_STAT,
- _("Could not stat %s"), fn);
+ _("Could not stat %s: %s"), fn, g_strerror (errno));
return NULL;
}
Modified: xfburn/trunk/xfburn/xfburn-transcoder-gst.c
===================================================================
--- xfburn/trunk/xfburn/xfburn-transcoder-gst.c 2008-10-26 23:59:52 UTC (rev 5829)
+++ xfburn/trunk/xfburn/xfburn-transcoder-gst.c 2008-10-27 01:18:12 UTC (rev 5830)
@@ -44,6 +44,7 @@
#include "xfburn-global.h"
#include "xfburn-error.h"
+#include "xfburn-settings.h"
#include "xfburn-transcoder-gst.h"
@@ -65,6 +66,7 @@
static gboolean prepare (XfburnTranscoder *trans, GError **error);
static gboolean transcode_next_track (XfburnTranscoderGst *trans, GError **error);
+static void finish (XfburnTranscoder *trans);
static gboolean free_burning_resources (XfburnTranscoder *trans, XfburnAudioTrack *atrack, GError **error);
static gboolean is_initialized (XfburnTranscoder *trans, GError **error);
@@ -79,11 +81,18 @@
LAST_SIGNAL,
};
+typedef enum {
+ XFBURN_TRANSCODER_GST_STATE_IDLE,
+ XFBURN_TRANSCODER_GST_STATE_IDENTIFYING,
+ XFBURN_TRANSCODER_GST_STATE_TRANSCODE_START,
+ XFBURN_TRANSCODER_GST_STATE_TRANSCODING,
+} XfburnTranscoderGstState;
+
typedef struct {
GstElement *pipeline;
GstElement *source, *decoder, *conv, *sink;
- gboolean is_transcoding;
+ XfburnTranscoderGstState state;
GCond *gst_cond;
GMutex *gst_mutex;
gboolean is_audio;
@@ -98,6 +107,7 @@
typedef struct {
int fd_in;
+ off_t size;
} XfburnAudioTrackGst;
#define SIGNAL_WAIT_TIMEOUT_MICROS 600000
@@ -105,6 +115,8 @@
#define SIGNAL_SEND_ITERATIONS 10
#define SIGNAL_SEND_TIMEOUT_MICROS 400000
+#define STATE_CHANGE_TIMEOUT_NANOS 250000000
+
#define XFBURN_AUDIO_TRACK_GET_GST(atrack) ((XfburnAudioTrackGst *) (atrack)->data)
/*********************/
@@ -202,6 +214,7 @@
iface->get_audio_track = get_audio_track;
iface->create_burn_track = create_burn_track;
iface->free_burning_resources = free_burning_resources;
+ iface->finish = finish;
iface->prepare = prepare;
}
@@ -218,6 +231,7 @@
GstBus *bus;
GstCaps *caps;
+ priv->state = XFBURN_TRANSCODER_GST_STATE_IDLE;
priv->pipeline = pipeline = gst_pipeline_new ("transcoder");
@@ -341,28 +355,33 @@
g_warning ("Gstreamer error: %s\n", error->message);
g_error_free (error);
- /* if transcoding, quit here, otherwise we're querying about songs */
- if (priv->is_transcoding) {
- DBG ("transcoding, not signaling on error");
- break;
- }
+ switch (priv->state) {
+ case XFBURN_TRANSCODER_GST_STATE_IDLE:
+ DBG ("Ignoring gstreamer error while idling.");
+ break;
+ case XFBURN_TRANSCODER_GST_STATE_IDENTIFYING:
+ priv->is_audio = FALSE;
+ DBG ("Trying to lock mutex (error)");
+ for (i=0; i<SIGNAL_SEND_ITERATIONS; i++) {
+ if (g_mutex_trylock (priv->gst_mutex))
+ break;
+ g_usleep (SIGNAL_SEND_TIMEOUT_MICROS / SIGNAL_SEND_ITERATIONS);
+ if (i==9) {
+ recreate_pipeline (trans);
+ g_warning ("Noone was there to listen to the gstreamer error: %s", error->message);
+ }
+ }
+ g_cond_signal (priv->gst_cond);
+ g_mutex_unlock (priv->gst_mutex);
+ DBG ("Releasing mutex (error)");
- priv->is_audio = FALSE;
- DBG ("Trying to lock mutex (error)");
- for (i=0; i<SIGNAL_SEND_ITERATIONS; i++) {
- if (g_mutex_trylock (priv->gst_mutex))
+ recreate_pipeline (trans);
break;
- g_usleep (SIGNAL_SEND_TIMEOUT_MICROS / SIGNAL_SEND_ITERATIONS);
- if (i==9) {
- recreate_pipeline (trans);
- g_warning ("Noone was there to listen to the gstreamer error: %s", error->message);
- }
+ case XFBURN_TRANSCODER_GST_STATE_TRANSCODE_START:
+ case XFBURN_TRANSCODER_GST_STATE_TRANSCODING:
+ g_error ("Gstreamer error while transcoding!");
+ break;
}
- g_cond_signal (priv->gst_cond);
- g_mutex_unlock (priv->gst_mutex);
- DBG ("Releasing mutex (error)");
-
- recreate_pipeline (trans);
break;
}
case GST_MESSAGE_STATE_CHANGED: {
@@ -379,40 +398,61 @@
else
DBG ("New state is %s, old is %s", state_to_str(state), state_to_str(old_state));
- if (state != GST_STATE_PAUSED)
- break;
-
- /* FIXME: just a debugging check, remove later */
- if (priv->is_transcoding) {
- DBG ("We should not be here while transcoding!");
- break;
- }
+ switch (priv->state) {
+ case XFBURN_TRANSCODER_GST_STATE_IDLE:
+ case XFBURN_TRANSCODER_GST_STATE_TRANSCODING:
+ DBG ("Not identifying, ignoring state change");
+ break;
+ case XFBURN_TRANSCODER_GST_STATE_IDENTIFYING:
- if (!g_mutex_trylock (priv->gst_mutex)) {
- DBG ("Lock held by another thread, not doing anything");
- return TRUE;
- } else {
- DBG ("Locked mutex");
- }
+ if (state != GST_STATE_PAUSED)
+ break;
+
+ if (!g_mutex_trylock (priv->gst_mutex)) {
+ DBG ("Lock held by another thread, not doing anything");
+ return TRUE;
+ } else {
+ DBG ("Locked mutex");
+ }
- fmt = GST_FORMAT_TIME;
- if (!gst_element_query_duration (priv->pipeline, &fmt, &priv->duration)) {
- g_mutex_unlock (priv->gst_mutex);
- DBG ("Could not query stream length!");
- return TRUE;
- }
+ fmt = GST_FORMAT_TIME;
+ if (!gst_element_query_duration (priv->pipeline, &fmt, &priv->duration)) {
+ g_mutex_unlock (priv->gst_mutex);
+ DBG ("Could not query stream length!");
+ return TRUE;
+ }
- secs = priv->duration / 1000000000;
- //DBG ("Length is %lldns = %ds = %lld bytes\n", priv->duration, secs, priv->duration * 176400 /1000000000);
- if (gst_element_set_state (priv->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
- DBG ("Failed to set state!");
+ secs = priv->duration / 1000000000;
+ //DBG ("Length is %lldns = %ds = %lld bytes\n", priv->duration, secs, priv->duration * 176400 /1000000000);
+ if (gst_element_set_state (priv->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
+ DBG ("Failed to set state!");
+ }
+
+ priv->is_audio = TRUE;
+ g_cond_signal (priv->gst_cond);
+ g_mutex_unlock (priv->gst_mutex);
+ DBG ("Releasing mutex (success)");
+ priv->state = XFBURN_TRANSCODER_GST_STATE_IDLE;
+
+ case XFBURN_TRANSCODER_GST_STATE_TRANSCODE_START:
+ if (state != GST_STATE_PLAYING)
+ break;
+
+ if (strcmp (GST_OBJECT_NAME (GST_MESSAGE_SRC (msg)), "decoder") != 0)
+ break;
+
+ if (!g_mutex_trylock (priv->gst_mutex)) {
+ DBG ("Lock held by another thread, can't signal transcoding start!");
+ break;
+ } else {
+ DBG ("Locked mutex");
+ }
+
+ g_cond_signal (priv->gst_cond);
+ g_mutex_unlock (priv->gst_mutex);
+ break;
}
- priv->is_audio = TRUE;
- g_cond_signal (priv->gst_cond);
- g_mutex_unlock (priv->gst_mutex);
- DBG ("Releasing mutex (success)");
-
break;
}
default:
@@ -471,12 +511,14 @@
XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (tgst);
XfburnAudioTrack *atrack;
+ XfburnAudioTrackGst *gtrack;
GTimeVal tv;
- guint size;
+ off_t size;
priv->is_audio = FALSE;
DBG ("setting filename for gstreamer");
+ priv->state = XFBURN_TRANSCODER_GST_STATE_IDENTIFYING;
g_object_set (G_OBJECT (priv->source), "location", fn, NULL);
if (gst_element_set_state (priv->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
g_warning ("Supposedly failed to change gstreamer state, ignoring it.");
@@ -513,8 +555,13 @@
atrack->sectors = size / AUDIO_BYTES_PER_SECTORS;
if (size % AUDIO_BYTES_PER_SECTORS > 0)
atrack->sectors++;
- DBG ("Track length = %d secs => size = %u bytes => %d sectors", atrack->length, size, atrack->sectors);
+ DBG ("Track length = %d secs => size = %.0f bytes => %d sectors", atrack->length, (float) size, atrack->sectors);
+ gtrack = g_new0 (XfburnAudioTrackGst, 1);
+ atrack->data = (gpointer) gtrack;
+
+ gtrack->size = size;
+
return atrack;
}
@@ -528,8 +575,9 @@
struct burn_track *track;
- XfburnAudioTrackGst *gtrack;
+ XfburnAudioTrackGst *gtrack = XFBURN_AUDIO_TRACK_GET_GST (atrack);
int pipe_fd[2];
+ struct burn_source *src_fifo;
if (pipe (pipe_fd) != 0) {
g_set_error (error, XFBURN_ERROR, XFBURN_ERROR_PIPE, g_strerror (errno));
@@ -549,7 +597,14 @@
close (pipe_fd[0]); close (pipe_fd[1]);
return NULL;
}
+
+ /* install fifo,
+ * its size will be a bit bigger in audio mode but that shouldn't matter */
+ src_fifo = burn_fifo_source_new (atrack->src, AUDIO_BYTES_PER_SECTORS, xfburn_settings_get_int ("fifo-size", FIFO_DEFAULT_SIZE) / 2, 0);
+ burn_source_free (atrack->src);
+ atrack->src = src_fifo;
+
track = burn_track_create ();
if (burn_track_set_source (track, atrack->src) != BURN_SOURCE_OK) {
@@ -562,11 +617,18 @@
return NULL;
}
- gtrack = g_new0 (XfburnAudioTrackGst, 1);
+ if (burn_track_set_size (track, gtrack->size) <= 0) {
+ g_set_error (error, XFBURN_ERROR, XFBURN_ERROR_BURN_TRACK,
+ _("Could not set track size for %s!"), atrack->inputfile);
+ XFBURN_AUDIO_TRACK_DELETE_DATA (atrack);
+ burn_source_free (atrack->src);
+ atrack->fd = -1;
+ close (pipe_fd[0]); close (pipe_fd[1]);
+ return NULL;
+ }
+
gtrack->fd_in = pipe_fd[1];
- atrack->data = (gpointer) gtrack;
-
//burn_track_set_byte_swap (track, TRUE);
burn_track_define_data (track, 0, 0, 1, BURN_AUDIO);
@@ -582,12 +644,26 @@
XfburnTranscoderGst *gst = XFBURN_TRANSCODER_GST (trans);
XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (gst);
gboolean ret;
+ GTimeVal tv;
priv->tracks = g_slist_reverse (priv->tracks);
- priv->is_transcoding = TRUE;
+ priv->state = XFBURN_TRANSCODER_GST_STATE_TRANSCODE_START;
ret = transcode_next_track (gst, error);
+ DBG ("Waiting for start signal");
+ g_get_current_time (&tv);
+ g_time_val_add (&tv, SIGNAL_WAIT_TIMEOUT_MICROS);
+ if (!g_cond_timed_wait (priv->gst_cond, priv->gst_mutex, &tv)) {
+ recreate_pipeline (gst);
+ g_set_error (error, XFBURN_ERROR, XFBURN_ERROR_GST_TIMEOUT,
+ _("Gstreamer did not want to start transcoding (timed out)"));
+ return FALSE;
+ }
+ DBG ("Got the start signal");
+
+ priv->state = XFBURN_TRANSCODER_GST_STATE_TRANSCODING;
+
/* give gstreamer a tiny bit of time.
* FIXME: what's a good time here?
* or rather, we should wait for the state change... */
@@ -599,8 +675,9 @@
static gboolean
transcode_next_track (XfburnTranscoderGst *trans, GError **error)
{
- XfburnTranscoderGst *basic = XFBURN_TRANSCODER_GST (trans);
- XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (basic);
+ XfburnTranscoderGst *gst = XFBURN_TRANSCODER_GST (trans);
+ XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (gst);
+
XfburnAudioTrack *atrack;
XfburnAudioTrackGst *gtrack;
@@ -626,19 +703,47 @@
return TRUE;
}
+static void
+finish (XfburnTranscoder *trans)
+{
+ XfburnTranscoderGst *gst = XFBURN_TRANSCODER_GST (trans);
+ XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (gst);
+
+ GstState state;
+ GstClock *clock;
+ GstClockTime tv;
+
+ DBG ("Done transcoding!");
+ priv->state = XFBURN_TRANSCODER_GST_STATE_IDLE;
+
+ clock = gst_element_get_clock (priv->pipeline);
+ tv = gst_clock_get_time (clock);
+ g_object_unref (clock);
+ tv += STATE_CHANGE_TIMEOUT_NANOS;
+
+ if (gst_element_get_state (priv->pipeline, &state, NULL, tv) == GST_STATE_CHANGE_FAILURE) {
+ DBG ("Could not query pipeline state, recreating it");
+ recreate_pipeline (gst);
+ return;
+ }
+
+ if ((state != GST_STATE_READY) &&
+ (gst_element_set_state (priv->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE)) {
+ DBG ("Could not make pipeline ready, recreating it");
+ recreate_pipeline (gst);
+ }
+}
+
static gboolean
free_burning_resources (XfburnTranscoder *trans, XfburnAudioTrack *atrack, GError **error)
{
- XfburnTranscoderGst *basic = XFBURN_TRANSCODER_GST (trans);
- XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (basic);
+ /*
+ XfburnTranscoderGst *gst = XFBURN_TRANSCODER_GST (trans);
+ XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (gst);
+ */
XfburnAudioTrackGst *gtrack = XFBURN_AUDIO_TRACK_GET_GST (atrack);
- /* is there a better place to put this?
- * It doesn't hurt that we execute it for every track, but it's just not so pretty */
- DBG ("Done transcoding!");
- priv->is_transcoding = FALSE;
-
close (gtrack->fd_in);
g_free (gtrack);
@@ -651,8 +756,8 @@
static gboolean
is_initialized (XfburnTranscoder *trans, GError **error)
{
- XfburnTranscoderGst *basic = XFBURN_TRANSCODER_GST (trans);
- XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (basic);
+ XfburnTranscoderGst *gst = XFBURN_TRANSCODER_GST (trans);
+ XfburnTranscoderGstPrivate *priv= XFBURN_TRANSCODER_GST_GET_PRIVATE (gst);
if (priv->error) {
*error = priv->error;
Modified: xfburn/trunk/xfburn/xfburn-transcoder.c
===================================================================
--- xfburn/trunk/xfburn/xfburn-transcoder.c 2008-10-26 23:59:52 UTC (rev 5829)
+++ xfburn/trunk/xfburn/xfburn-transcoder.c 2008-10-27 01:18:12 UTC (rev 5830)
@@ -152,6 +152,17 @@
return TRUE;
}
+void
+xfburn_transcoder_finish (XfburnTranscoder *trans)
+{
+ XfburnTranscoderInterface *iface = XFBURN_TRANSCODER_GET_INTERFACE (trans);
+
+ if (iface->finish)
+ iface->finish (trans);
+
+ /* this function is not required by the interface */
+}
+
gboolean
xfburn_transcoder_free_burning_resources (XfburnTranscoder *trans, XfburnAudioTrack *atrack, GError **error)
{
Modified: xfburn/trunk/xfburn/xfburn-transcoder.h
===================================================================
--- xfburn/trunk/xfburn/xfburn-transcoder.h 2008-10-26 23:59:52 UTC (rev 5829)
+++ xfburn/trunk/xfburn/xfburn-transcoder.h 2008-10-27 01:18:12 UTC (rev 5830)
@@ -68,8 +68,9 @@
struct burn_track * (*create_burn_track) (XfburnTranscoder *trans, XfburnAudioTrack *atrack, GError **error);
/* optional functions */
+ gboolean (*prepare) (XfburnTranscoder *trans, GError **error);
+ void (*finish) (XfburnTranscoder *trans);
gboolean (*free_burning_resources) (XfburnTranscoder *trans, XfburnAudioTrack *atrack, GError **error);
- gboolean (*prepare) (XfburnTranscoder *trans, GError **error);
} XfburnTranscoderInterface;
@@ -84,8 +85,9 @@
struct burn_track *xfburn_transcoder_create_burn_track (XfburnTranscoder *trans, XfburnAudioTrack *atrack, GError **error);
/* optional functions */
+gboolean xfburn_transcoder_prepare (XfburnTranscoder *trans, GError **error);
+void xfburn_transcoder_finish (XfburnTranscoder *trans);
gboolean xfburn_transcoder_free_burning_resources (XfburnTranscoder *trans, XfburnAudioTrack *atrack, GError **error);
-gboolean xfburn_transcoder_prepare (XfburnTranscoder *trans, GError **error);
/* defined purely by the interface */
void xfburn_transcoder_free_track (XfburnTranscoder *trans, XfburnAudioTrack *atrack);
More information about the Goodies-commits
mailing list