gmyth-stream/gmemcoder/src/gmencoder.c
branchtrunk
changeset 807 add4025ca678
parent 804 4b2192319f56
child 810 fcf0bc36025a
     1.1 --- a/gmyth-stream/gmemcoder/src/gmencoder.c	Wed Aug 15 20:52:44 2007 +0100
     1.2 +++ b/gmyth-stream/gmemcoder/src/gmencoder.c	Thu Aug 16 14:46:11 2007 +0100
     1.3 @@ -18,6 +18,9 @@
     1.4  #define G_MENCODER_GET_PRIVATE(obj) \
     1.5      (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
     1.6  
     1.7 +#define USE_MANUAL_SINK
     1.8 +#define GMENCODER_TIMEOUT	5000
     1.9 +
    1.10  typedef struct _GMencoderPrivate GMencoderPrivate;
    1.11  typedef struct _SetupInfo SetupInfo;
    1.12  
    1.13 @@ -42,7 +45,7 @@
    1.14      GstElement     *sink;
    1.15      GstElement     *src;
    1.16  
    1.17 -    gint out_fd;
    1.18 +    GnomeVFSHandle  *handle;
    1.19  
    1.20      gboolean        ready;
    1.21      SetupInfo      *info;
    1.22 @@ -52,7 +55,7 @@
    1.23      gint            tick_id;
    1.24      gint64          duration;
    1.25      gboolean        send_chunked;
    1.26 -
    1.27 +    gint 	    timeout_id;
    1.28  
    1.29      //V4l info
    1.30      GstElement *v4lsrc;
    1.31 @@ -110,10 +113,16 @@
    1.32                                      gchar ** audio_encode_prop,
    1.33                                      guint audio_rate,
    1.34  				    gboolean deinterlace);
    1.35 +static gboolean	_process_timeout_cb (gpointer user_data);
    1.36 +#ifdef USE_MANUAL_SINK
    1.37  static void _flush_queue	        (GMencoder *self);
    1.38  static void _buffer_arrive_cb       (GstElement* object,
    1.39                                       GstBuffer* buff,
    1.40 +                                     GstPad* pad,
    1.41                                       gpointer user_data);
    1.42 +#endif
    1.43 +
    1.44 +
    1.45  static gboolean _tick_cb(gpointer data);
    1.46  
    1.47  static guint    g_mencoder_signals[LAST_SIGNAL] = { 0 };
    1.48 @@ -638,7 +647,15 @@
    1.49      g_return_if_fail(priv->ready == FALSE);
    1.50      priv->ready = TRUE;
    1.51      gst_element_set_state(priv->pipe, GST_STATE_PLAYING);
    1.52 +    if (priv->tick_id != 0) {
    1.53 +        g_source_remove (priv->tick_id);
    1.54 +    }
    1.55      priv->tick_id = g_timeout_add(500, _tick_cb, self);
    1.56 +
    1.57 +    if (priv->timeout_id != 0) {
    1.58 +        g_source_remove (priv->timeout_id);
    1.59 +    }
    1.60 +    priv->timeout_id = g_timeout_add(GMENCODER_TIMEOUT, _process_timeout_cb, self);
    1.61  }
    1.62  
    1.63  void
    1.64 @@ -659,6 +676,11 @@
    1.65          priv->tick_id = 0;
    1.66      }
    1.67  
    1.68 +    if (priv->timeout_id != 0) {
    1.69 +        g_source_remove (priv->timeout_id);
    1.70 +	priv->timeout_id = 0;
    1.71 +    }
    1.72 +
    1.73      if (priv->pipe != NULL) {
    1.74          // TODO: fixe pipeline dispose
    1.75          //gst_element_set_state (priv->pipe, GST_STATE_NULL);
    1.76 @@ -670,6 +692,7 @@
    1.77          priv->pipe = NULL;
    1.78          priv->abin = NULL;
    1.79          priv->vbin = NULL;
    1.80 +        priv->sink = NULL;
    1.81      }
    1.82      priv->ready = FALSE;
    1.83  }
    1.84 @@ -694,10 +717,8 @@
    1.85      GstElement     *abin = NULL;
    1.86      GstElement     *vbin = NULL;
    1.87      GstElement     *queue = NULL;
    1.88 -    GstElement     *identity = NULL;
    1.89      GstPad         *aux_pad = NULL;
    1.90      GstPad         *mux_pad = NULL;
    1.91 -    GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
    1.92  
    1.93      pipe = gst_pipeline_new("pipe");
    1.94  
    1.95 @@ -708,10 +729,11 @@
    1.96          goto error;
    1.97  
    1.98      queue = gst_element_factory_make("queue", "queueu_sink");
    1.99 -    identity = gst_element_factory_make ("identity", "identity");
   1.100 -    sink = gst_element_factory_make("fdsink", "sink");
   1.101 -    g_object_set (sink, "fd", priv->out_fd, NULL);
   1.102 -    g_signal_connect (G_OBJECT (identity),
   1.103 +
   1.104 +
   1.105 +    sink = gst_element_factory_make("fakesink", "sink");
   1.106 +    g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
   1.107 +    g_signal_connect (G_OBJECT (sink),
   1.108                        "handoff",
   1.109                        G_CALLBACK (_buffer_arrive_cb),
   1.110                        self);
   1.111 @@ -727,7 +749,7 @@
   1.112          goto error;
   1.113  
   1.114      // Finish Pipe
   1.115 -    gst_bin_add_many(GST_BIN(pipe), abin, vbin, mux, queue, identity, sink, NULL);
   1.116 +    gst_bin_add_many(GST_BIN(pipe), abin, vbin, mux, queue, sink, NULL);
   1.117  
   1.118  
   1.119      // Link bins with mux
   1.120 @@ -767,12 +789,11 @@
   1.121      mux_pad = NULL;
   1.122  
   1.123      // Link mux with sink
   1.124 -    gst_element_link_many(mux, queue, identity, sink, NULL);
   1.125 +    gst_element_link_many(mux, queue, sink, NULL);
   1.126  
   1.127      bus = gst_pipeline_get_bus(GST_PIPELINE(pipe));
   1.128      gst_bus_add_watch(bus, _pipeline_bus_cb, self);
   1.129      gst_object_unref(bus);
   1.130 -
   1.131      return pipe;
   1.132  
   1.133    error:
   1.134 @@ -928,19 +949,24 @@
   1.135  _open_output(GMencoder * self, const gchar * uri)
   1.136  {
   1.137      gchar         **i;
   1.138 +    GnomeVFSResult result;
   1.139      GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
   1.140  
   1.141 -    priv->out_fd = 0;
   1.142 -
   1.143      i = g_strsplit(uri, "://", 0);
   1.144      if (strcmp(i[0], "fd") == 0) {
   1.145 -        priv->out_fd = atoi (i[1]);
   1.146 +        result = gnome_vfs_open_fd (&priv->handle, atoi(i[1]));
   1.147      } else {
   1.148 -        priv->out_fd = open (i[1], O_CREAT|O_WRONLY|O_TRUNC, 0666);
   1.149 +        if (g_file_test (i[1], G_FILE_TEST_EXISTS) == FALSE) {
   1.150 +            result = gnome_vfs_create (&priv->handle, uri, GNOME_VFS_OPEN_WRITE, TRUE,
   1.151 +                              GNOME_VFS_PERM_USER_WRITE | GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_GROUP_READ);
   1.152 +        } else {
   1.153 +            result = gnome_vfs_open (&priv->handle, uri,
   1.154 +                                     GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_TRUNCATE);
   1.155 +        }
   1.156      }
   1.157  
   1.158      g_strfreev(i);
   1.159 -    return (priv->out_fd > 0);
   1.160 +    return (result == GNOME_VFS_OK);
   1.161  }
   1.162  
   1.163  static          gboolean
   1.164 @@ -1003,7 +1029,9 @@
   1.165  
   1.166      case GST_MESSAGE_EOS:
   1.167          priv->ready = FALSE;
   1.168 +#ifdef USE_MANUAL_SINK
   1.169          _flush_queue (G_MENCODER (user_data));
   1.170 +#endif
   1.171          g_signal_emit(user_data, g_mencoder_signals[EOS], 0);
   1.172          break;
   1.173  
   1.174 @@ -1085,40 +1113,50 @@
   1.175      return TRUE;
   1.176  }
   1.177  
   1.178 +static gboolean 
   1.179 +_process_timeout_cb (gpointer user_data)
   1.180 +{
   1.181 +    GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
   1.182  
   1.183 -static void
   1.184 -_chunke_buffer (GstBuffer *buf)
   1.185 +    g_signal_emit(user_data, g_mencoder_signals[ERROR], 0, "timeout");
   1.186 +    priv->timeout_id = 0;
   1.187 +    return FALSE;
   1.188 +}
   1.189 +
   1.190 +
   1.191 +#ifdef USE_MANUAL_SINK
   1.192 +static gboolean
   1.193 +_send_buffer (GnomeVFSHandle *handle, gpointer buff, gint size)
   1.194  {
   1.195      gchar *msg;
   1.196      GByteArray *b_send;
   1.197 +    GnomeVFSResult result;
   1.198 +    GnomeVFSFileSize bytes_written;
   1.199  
   1.200      b_send = g_byte_array_new ();
   1.201 -    msg = g_strdup_printf ("%x\r\n", GST_BUFFER_SIZE(buf));
   1.202 +    msg = g_strdup_printf ("%x\r\n", size);
   1.203      b_send = g_byte_array_append (b_send, (const guint8*) msg, strlen (msg) * sizeof (gchar));
   1.204      g_free (msg);
   1.205  
   1.206 -    b_send = g_byte_array_append (b_send, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
   1.207 +    b_send = g_byte_array_append (b_send, buff, size);
   1.208  
   1.209      msg = g_strdup ("\r\n");
   1.210      b_send = g_byte_array_append (b_send, (const guint8*) msg, strlen (msg) * sizeof (gchar));
   1.211      g_free (msg);
   1.212  
   1.213 -    g_free (GST_BUFFER_DATA(buf));
   1.214 +    result = gnome_vfs_write (handle, b_send->data, b_send->len, &bytes_written);
   1.215 +    g_byte_array_free (b_send, TRUE);
   1.216  
   1.217 -    GST_BUFFER_SIZE(buf)=b_send->len;
   1.218 -    GST_BUFFER_DATA(buf)=b_send->data;
   1.219 -
   1.220 -    g_byte_array_free (b_send, FALSE);
   1.221 +    return (result == GNOME_VFS_OK);
   1.222  }
   1.223  
   1.224  static void
   1.225  _flush_queue (GMencoder *self)
   1.226  {
   1.227 -    /*
   1.228      GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
   1.229  
   1.230 -    
   1.231      if (priv->send_chunked) {
   1.232 +        GnomeVFSFileSize bytes_written;
   1.233          gchar *end_msg;
   1.234          end_msg = g_strdup ("0\r\n\r\n");
   1.235          gnome_vfs_write (priv->handle,
   1.236 @@ -1127,17 +1165,46 @@
   1.237                           &bytes_written);
   1.238          g_free (end_msg);
   1.239      }
   1.240 -    */
   1.241  }
   1.242  
   1.243  static void
   1.244  _buffer_arrive_cb (GstElement* object,
   1.245 -                   GstBuffer* buf,
   1.246 +                   GstBuffer* buff,
   1.247 +                   GstPad* pad,
   1.248                     gpointer user_data)
   1.249  {
   1.250      GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
   1.251  
   1.252 +    if (priv->timeout_id != 0) {
   1.253 +	g_source_remove (priv->timeout_id);
   1.254 +	priv->timeout_id = 0;
   1.255 +    }
   1.256 +
   1.257      if (priv->send_chunked) {
   1.258 -         _chunke_buffer (buf);
   1.259 +        if (_send_buffer (priv->handle, GST_BUFFER_DATA (buff), GST_BUFFER_SIZE (buff)) == FALSE)
   1.260 +            goto error;
   1.261 +    } else {
   1.262 +        GnomeVFSResult result;
   1.263 +        GnomeVFSFileSize bytes_written;
   1.264 +
   1.265 +        result = gnome_vfs_write (priv->handle,
   1.266 +                                  GST_BUFFER_DATA (buff),
   1.267 +                                  GST_BUFFER_SIZE (buff),
   1.268 +                                  &bytes_written);
   1.269 +
   1.270 +        if (result != GNOME_VFS_OK)
   1.271 +            goto error;
   1.272      }
   1.273 +
   1.274 +    return;
   1.275 +
   1.276 +error:
   1.277 +    if (priv->tick_id != 0) {
   1.278 +        g_source_remove(priv->tick_id);
   1.279 +        priv->tick_id = 0;
   1.280 +    }
   1.281 +    g_signal_emit(user_data, g_mencoder_signals[ERROR], 0, "Fail to write on socket");
   1.282 +    gst_element_set_state (priv->pipe, GST_STATE_PAUSED);
   1.283  }
   1.284 +
   1.285 +#endif