gst-gmyth/concatmux/gstconcatmux.c
author rosfran
Thu May 31 16:02:53 2007 +0100 (2007-05-31)
branchtrunk
changeset 725 a102805611e7
parent 611 aa1f309ec686
child 751 3cf3c6019e3b
permissions -rw-r--r--
[svn r731] Fixed bug with the program chain changing.
renatofilho@609
     1
/* concat muxer plugin for GStreamer
renatofilho@609
     2
 * Copyright (C) 2004 Renato Filhps <renato.filho@indt.org.br>
renatofilho@609
     3
 *
renatofilho@609
     4
 * This library is free software; you can redistribute it and/or
renatofilho@609
     5
 * modify it under the terms of the GNU Library General Public
renatofilho@609
     6
 * License as published by the Free Software Foundation; either
renatofilho@609
     7
 * version 2 of the License, or (at your option) any later version.
renatofilho@609
     8
 *
renatofilho@609
     9
 * This library is distributed in the hope that it will be useful,
renatofilho@609
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
renatofilho@609
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
renatofilho@609
    12
 * Library General Public License for more details.
renatofilho@609
    13
 *
renatofilho@609
    14
 * You should have received a copy of the GNU Library General Public
renatofilho@609
    15
 * License along with this library; if not, write to the
renatofilho@609
    16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
renatofilho@609
    17
 * Boston, MA 02111-1307, USA.
renatofilho@609
    18
 */
renatofilho@609
    19
renatofilho@609
    20
/**
renatofilho@609
    21
 * SECTION:element-concatmux
renatofilho@609
    22
 * @short_description: Concat that takes one or several digital streams
renatofilho@609
    23
 * and muxes them to a single stream.
renatofilho@609
    24
 *
renatofilho@609
    25
 * <refsect2>
renatofilho@609
    26
 * <title>Sample pipelines</title>
renatofilho@609
    27
 * <para>
renatofilho@609
    28
 * Here is a simple pipeline to concat 2 files into a another file:
renatofilho@609
    29
 * <programlisting>
renatofilho@609
    30
 * gst-launch concatmux name=m ! filesink location=output.txt  filesrc location=file_a.txt !  m. filesrc location=file_b.txt ! m.
renatofilho@609
    31
 * </programlisting>
renatofilho@609
    32
 * </para>
renatofilho@609
    33
 * </refsect2>
renatofilho@609
    34
 */
renatofilho@609
    35
renatofilho@609
    36
#ifdef HAVE_CONFIG_H
renatofilho@609
    37
#include "config.h"
renatofilho@609
    38
#endif
renatofilho@609
    39
renatofilho@609
    40
#include <gst/gst.h>
renatofilho@609
    41
#include <gst/base/gstcollectpads.h>
renatofilho@609
    42
renatofilho@609
    43
#include <string.h>
renatofilho@609
    44
renatofilho@609
    45
GST_DEBUG_CATEGORY_STATIC (gst_concat_mux_debug);
renatofilho@609
    46
#define GST_CAT_DEFAULT gst_concat_mux_debug
renatofilho@609
    47
renatofilho@609
    48
#define GST_TYPE_CONCAT_MUX (gst_concat_mux_get_type())
renatofilho@609
    49
#define GST_CONCAT_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CONCAT_MUX, GstConcatMux))
renatofilho@609
    50
#define GST_CONCAT_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CONCAT_MUX, GstConcatMux))
renatofilho@609
    51
#define GST_IS_CONCAT_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CONCAT_MUX))
renatofilho@609
    52
#define GST_IS_CONCAT_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CONCAT_MUX))
renatofilho@609
    53
renatofilho@609
    54
typedef struct _GstConcatMux GstConcatMux;
renatofilho@609
    55
typedef struct _GstConcatMuxClass GstConcatMuxClass;
renatofilho@609
    56
renatofilho@609
    57
/**
renatofilho@609
    58
 * GstConcatMux:
renatofilho@609
    59
 *
renatofilho@609
    60
 * The opaque #GstConcatMux structure.
renatofilho@609
    61
 */
renatofilho@609
    62
struct _GstConcatMux
renatofilho@609
    63
{
renatofilho@609
    64
  GstElement element;
renatofilho@609
    65
renatofilho@609
    66
  /* Caps */
renatofilho@609
    67
  GstCaps *sink_caps;
renatofilho@609
    68
renatofilho@609
    69
  /* pad */
renatofilho@609
    70
  GstPad *srcpad;
renatofilho@609
    71
  GstPad *sinkpad;
renatofilho@609
    72
renatofilho@609
    73
  /* sinkpads */
renatofilho@609
    74
  GSList *sinks;
renatofilho@609
    75
  gint numpads;
renatofilho@609
    76
renatofilho@609
    77
  /* offset in stream */
renatofilho@609
    78
  guint64 offset;
renatofilho@609
    79
  guint64 timeoffset;
renatofilho@609
    80
  guint64 start_time;
renatofilho@609
    81
renatofilho@609
    82
  gboolean negotiated;
renatofilho@609
    83
  gboolean resync;
renatofilho@609
    84
  gboolean done;
renatofilho@609
    85
};
renatofilho@609
    86
renatofilho@609
    87
struct _GstConcatMuxClass
renatofilho@609
    88
{
renatofilho@609
    89
  GstElementClass parent_class;
renatofilho@609
    90
};
renatofilho@609
    91
renatofilho@609
    92
/* elementfactory information */
renatofilho@609
    93
static const GstElementDetails gst_concat_mux_details =
renatofilho@609
    94
GST_ELEMENT_DETAILS ("Concat muxer",
renatofilho@609
    95
    "Codec/Muxer",
renatofilho@609
    96
    "mux concat streams",
renatofilho@609
    97
    "Renato Filho <renato.filho@indt.org>");
renatofilho@609
    98
renatofilho@609
    99
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
renatofilho@609
   100
    GST_PAD_SRC,
renatofilho@609
   101
    GST_PAD_ALWAYS,
renatofilho@609
   102
    GST_STATIC_CAPS_ANY
renatofilho@609
   103
    );
renatofilho@609
   104
renatofilho@609
   105
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d",
renatofilho@609
   106
    GST_PAD_SINK,
renatofilho@609
   107
    GST_PAD_REQUEST,
renatofilho@609
   108
    GST_STATIC_CAPS_ANY         
renatofilho@609
   109
    );
renatofilho@609
   110
renatofilho@609
   111
static void gst_concat_mux_base_init (gpointer g_class);
renatofilho@609
   112
static void gst_concat_mux_class_init (GstConcatMuxClass * klass);
renatofilho@609
   113
static void gst_concat_mux_init (GstConcatMux * concat_mux);
renatofilho@609
   114
renatofilho@609
   115
static void gst_concat_mux_finalize (GObject * object);
renatofilho@609
   116
renatofilho@609
   117
static gboolean gst_concat_mux_handle_src_event (GstPad * pad,
renatofilho@609
   118
    GstEvent * event);
renatofilho@609
   119
static gboolean gst_concat_mux_handle_sink_event (GstPad * pad,
renatofilho@609
   120
    GstEvent * event);
renatofilho@609
   121
renatofilho@609
   122
static GstPad *gst_concat_mux_request_new_pad (GstElement * element,
renatofilho@609
   123
    GstPadTemplate * templ, const gchar * name);
renatofilho@609
   124
static GstStateChangeReturn gst_concat_mux_change_state (GstElement *
renatofilho@609
   125
    element, GstStateChange transition);
renatofilho@609
   126
renatofilho@609
   127
static GstFlowReturn gst_concat_mux_chain (GstPad * pad,  GstBuffer * buf);
renatofilho@609
   128
static void gst_concat_mux_clear (GstConcatMux *mux);
renatofilho@609
   129
renatofilho@609
   130
renatofilho@609
   131
static GstElementClass *parent_class = NULL;
renatofilho@609
   132
renatofilho@609
   133
GType
renatofilho@609
   134
gst_concat_mux_get_type (void)
renatofilho@609
   135
{
renatofilho@609
   136
  static GType concat_mux_type = 0;
renatofilho@609
   137
renatofilho@609
   138
  if (!concat_mux_type) {
renatofilho@609
   139
    static const GTypeInfo concat_mux_info = {
renatofilho@609
   140
      sizeof (GstConcatMuxClass),
renatofilho@609
   141
      gst_concat_mux_base_init,
renatofilho@609
   142
      NULL,
renatofilho@609
   143
      (GClassInitFunc) gst_concat_mux_class_init,
renatofilho@609
   144
      NULL,
renatofilho@609
   145
      NULL,
renatofilho@609
   146
      sizeof (GstConcatMux),
renatofilho@609
   147
      0,
renatofilho@609
   148
      (GInstanceInitFunc) gst_concat_mux_init,
renatofilho@609
   149
    };
renatofilho@609
   150
renatofilho@609
   151
    concat_mux_type =
renatofilho@609
   152
        g_type_register_static (GST_TYPE_ELEMENT, "GstConcatMux",
renatofilho@609
   153
        &concat_mux_info, 0);
renatofilho@609
   154
  }
renatofilho@609
   155
  return concat_mux_type;
renatofilho@609
   156
}
renatofilho@609
   157
renatofilho@609
   158
static void
renatofilho@609
   159
gst_concat_mux_base_init (gpointer g_class)
renatofilho@609
   160
{
renatofilho@609
   161
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
renatofilho@609
   162
renatofilho@609
   163
  gst_element_class_add_pad_template (element_class,
renatofilho@609
   164
      gst_static_pad_template_get (&src_factory));
renatofilho@609
   165
  gst_element_class_add_pad_template (element_class,
renatofilho@609
   166
      gst_static_pad_template_get (&sink_factory));
renatofilho@609
   167
renatofilho@609
   168
  gst_element_class_set_details (element_class, &gst_concat_mux_details);
renatofilho@609
   169
}
renatofilho@609
   170
renatofilho@609
   171
static void
renatofilho@609
   172
gst_concat_mux_class_init (GstConcatMuxClass * klass)
renatofilho@609
   173
{
renatofilho@609
   174
  GObjectClass *gobject_class;
renatofilho@609
   175
  GstElementClass *gstelement_class;
renatofilho@609
   176
renatofilho@609
   177
  gobject_class = (GObjectClass *) klass;
renatofilho@609
   178
  gstelement_class = (GstElementClass *) klass;
renatofilho@609
   179
renatofilho@609
   180
  parent_class = g_type_class_peek_parent (klass);
renatofilho@609
   181
renatofilho@609
   182
  gobject_class->finalize = gst_concat_mux_finalize;
renatofilho@609
   183
renatofilho@609
   184
  gstelement_class->request_new_pad = gst_concat_mux_request_new_pad;
renatofilho@609
   185
  gstelement_class->change_state = gst_concat_mux_change_state;
renatofilho@609
   186
}
renatofilho@609
   187
renatofilho@609
   188
static void
renatofilho@609
   189
gst_concat_mux_init (GstConcatMux * concat_mux)
renatofilho@609
   190
{
renatofilho@609
   191
  GstElementClass *klass = GST_ELEMENT_GET_CLASS (concat_mux);
renatofilho@609
   192
renatofilho@609
   193
  concat_mux->srcpad =
renatofilho@609
   194
      gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
renatofilho@609
   195
          "src"), "src");
renatofilho@609
   196
  gst_pad_set_event_function (concat_mux->srcpad,
renatofilho@609
   197
      gst_concat_mux_handle_src_event);
renatofilho@609
   198
  gst_element_add_pad (GST_ELEMENT (concat_mux), concat_mux->srcpad);
renatofilho@609
   199
}
renatofilho@609
   200
renatofilho@609
   201
static void
renatofilho@609
   202
gst_concat_mux_finalize (GObject * object)
renatofilho@609
   203
{
renatofilho@609
   204
  GstConcatMux *concat_mux;
renatofilho@609
   205
renatofilho@609
   206
  concat_mux = GST_CONCAT_MUX (object);
renatofilho@609
   207
  gst_concat_mux_clear (GST_CONCAT_MUX (object));
renatofilho@609
   208
renatofilho@609
   209
  G_OBJECT_CLASS (parent_class)->finalize (object);
renatofilho@609
   210
}
renatofilho@609
   211
renatofilho@609
   212
static void
renatofilho@609
   213
gst_concat_mux_free_pad (gpointer data,
renatofilho@609
   214
                            gpointer user_data)
renatofilho@609
   215
{
renatofilho@609
   216
   GMutex *mux;
renatofilho@609
   217
renatofilho@609
   218
   mux = gst_pad_get_element_private (GST_PAD (data));
renatofilho@609
   219
   g_mutex_unlock (mux);
renatofilho@609
   220
   g_mutex_free (mux);
renatofilho@609
   221
   gst_object_unref (GST_OBJECT (data)); 
renatofilho@609
   222
}
renatofilho@609
   223
renatofilho@609
   224
static void
renatofilho@609
   225
gst_concat_mux_clear (GstConcatMux *mux)
renatofilho@609
   226
{
renatofilho@609
   227
  mux->resync = TRUE;
renatofilho@609
   228
  mux->timeoffset = 0;
renatofilho@609
   229
  mux->offset = 0;
renatofilho@609
   230
  mux->negotiated = FALSE;
renatofilho@609
   231
  mux->done = TRUE;
renatofilho@609
   232
  if (mux->sinks != NULL) {
renatofilho@609
   233
    g_slist_foreach (mux->sinks, gst_concat_mux_free_pad, mux);
renatofilho@609
   234
    g_slist_free (mux->sinks);
renatofilho@609
   235
    mux->sinks = NULL;
renatofilho@609
   236
  }
renatofilho@609
   237
}
renatofilho@609
   238
renatofilho@609
   239
renatofilho@609
   240
static GstPadLinkReturn
renatofilho@609
   241
gst_concat_mux_sinkconnect (GstPad * pad, GstPad * peer)
renatofilho@609
   242
{
renatofilho@609
   243
  gchar *pad_name = NULL;
renatofilho@609
   244
  GstConcatMux *concat_mux;
renatofilho@609
   245
renatofilho@609
   246
  concat_mux = GST_CONCAT_MUX (gst_pad_get_parent (pad));
renatofilho@609
   247
renatofilho@609
   248
  if (concat_mux->sink_caps != NULL) {
renatofilho@609
   249
      GstCaps *peer_caps = gst_pad_get_caps (peer);
renatofilho@609
   250
      GstCaps *intersect;
renatofilho@609
   251
renatofilho@609
   252
      intersect =  gst_caps_intersect (concat_mux->sink_caps, peer_caps);
renatofilho@609
   253
      if (intersect == NULL) {
renatofilho@609
   254
          gst_caps_unref (peer_caps);
renatofilho@609
   255
          return GST_PAD_LINK_NOFORMAT;
renatofilho@609
   256
      }
renatofilho@609
   257
      gst_caps_unref (peer_caps);
renatofilho@609
   258
      gst_caps_unref (intersect);
renatofilho@609
   259
  } else {
renatofilho@609
   260
      concat_mux->sink_caps = gst_pad_get_caps (pad);
renatofilho@609
   261
  }
renatofilho@609
   262
renatofilho@609
   263
  pad_name = gst_pad_get_name (pad);
renatofilho@609
   264
renatofilho@609
   265
  GST_DEBUG_OBJECT (concat_mux, "sinkconnect triggered on %s", pad_name);
renatofilho@609
   266
renatofilho@609
   267
  g_free (pad_name);
renatofilho@609
   268
renatofilho@609
   269
  gst_object_unref (concat_mux);
renatofilho@609
   270
renatofilho@609
   271
  return GST_PAD_LINK_OK;
renatofilho@609
   272
}
renatofilho@609
   273
renatofilho@609
   274
static GstPad *
renatofilho@609
   275
gst_concat_mux_request_new_pad (GstElement * element,
renatofilho@609
   276
    GstPadTemplate * templ, const gchar * req_name)
renatofilho@609
   277
{
renatofilho@609
   278
  GstConcatMux *concat_mux;
renatofilho@609
   279
  GstPad *newpad;
renatofilho@609
   280
  GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
renatofilho@609
   281
  GMutex *mutex;
renatofilho@609
   282
renatofilho@609
   283
  g_return_val_if_fail (templ != NULL, NULL);
renatofilho@609
   284
renatofilho@609
   285
  if (templ->direction != GST_PAD_SINK) {
renatofilho@609
   286
    g_warning ("concat_mux: request pad that is not a SINK pad\n");
renatofilho@609
   287
    return NULL;
renatofilho@609
   288
  }
renatofilho@609
   289
renatofilho@609
   290
  g_return_val_if_fail (GST_IS_CONCAT_MUX (element), NULL);
renatofilho@609
   291
renatofilho@609
   292
  concat_mux = GST_CONCAT_MUX (element);
renatofilho@609
   293
renatofilho@609
   294
  if (templ == gst_element_class_get_pad_template (klass, "sink_%d")) {
renatofilho@609
   295
    gchar *name;
renatofilho@609
   296
renatofilho@609
   297
    /* create new pad with the name */
renatofilho@609
   298
    name = g_strdup_printf ("sink_%02d", concat_mux->numpads);
renatofilho@609
   299
    g_debug ("NEw pad %s", name);
renatofilho@609
   300
    newpad = gst_pad_new_from_template (templ, name);
renatofilho@609
   301
    g_free (name);
renatofilho@609
   302
    concat_mux->sinks = g_slist_append (concat_mux->sinks, newpad);
renatofilho@609
   303
    g_debug ("New sink %p / %d", newpad, g_slist_length (concat_mux->sinks));
renatofilho@609
   304
    concat_mux->numpads++;
renatofilho@609
   305
  } else {
renatofilho@609
   306
    g_warning ("concat_mux: this is not our template!\n");
renatofilho@609
   307
    return NULL;
renatofilho@609
   308
  }
renatofilho@609
   309
renatofilho@609
   310
  mutex = g_mutex_new ();
renatofilho@609
   311
renatofilho@609
   312
  if (concat_mux->sinkpad == NULL) {
renatofilho@609
   313
      concat_mux->sinkpad = newpad;
renatofilho@609
   314
  }
renatofilho@609
   315
  else {
renatofilho@609
   316
      g_mutex_lock (mutex);
renatofilho@609
   317
  }
renatofilho@609
   318
renatofilho@609
   319
  gst_pad_set_element_private (newpad, mutex);
renatofilho@609
   320
  /* setup some pad functions */
renatofilho@609
   321
  gst_pad_set_link_function (newpad, gst_concat_mux_sinkconnect);
renatofilho@609
   322
  gst_pad_set_event_function (newpad, gst_concat_mux_handle_sink_event);
renatofilho@609
   323
  gst_pad_set_chain_function (newpad, gst_concat_mux_chain);
renatofilho@609
   324
renatofilho@609
   325
  /* add the pad to the element */
renatofilho@609
   326
  gst_element_add_pad (element, newpad);
renatofilho@609
   327
renatofilho@609
   328
  return newpad;
renatofilho@609
   329
}
renatofilho@609
   330
renatofilho@609
   331
/* handle events */
renatofilho@609
   332
static gboolean
renatofilho@609
   333
gst_concat_mux_handle_src_event (GstPad * pad, GstEvent * event)
renatofilho@609
   334
{
renatofilho@609
   335
  GstConcatMux *concat_mux;
renatofilho@609
   336
  GstEventType type;
renatofilho@609
   337
renatofilho@609
   338
  concat_mux = GST_CONCAT_MUX (gst_pad_get_parent (pad));
renatofilho@609
   339
renatofilho@609
   340
  type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
renatofilho@609
   341
renatofilho@609
   342
  switch (type) {
renatofilho@609
   343
    case GST_EVENT_SEEK:
renatofilho@609
   344
      /* disable seeking for now */
renatofilho@609
   345
      return FALSE;
renatofilho@609
   346
    default:
renatofilho@609
   347
      break;
renatofilho@609
   348
  }
renatofilho@609
   349
renatofilho@609
   350
  gst_object_unref (concat_mux);
renatofilho@609
   351
renatofilho@609
   352
  return gst_pad_event_default (pad, event);
renatofilho@609
   353
}
renatofilho@609
   354
renatofilho@609
   355
/* handle events */
renatofilho@609
   356
static gboolean
renatofilho@609
   357
gst_concat_mux_handle_sink_event (GstPad * pad, GstEvent * event)
renatofilho@609
   358
{
renatofilho@609
   359
  GstConcatMux *mux;
renatofilho@609
   360
  GstEventType type;
renatofilho@609
   361
renatofilho@609
   362
  mux = GST_CONCAT_MUX (gst_pad_get_parent (pad));
renatofilho@609
   363
renatofilho@609
   364
  type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
renatofilho@609
   365
renatofilho@609
   366
  switch (type) {
renatofilho@609
   367
    case GST_EVENT_EOS:
renatofilho@609
   368
    {
renatofilho@609
   369
        mux->resync = TRUE;
renatofilho@609
   370
        g_debug ("sink EOS %p / %d", pad, g_slist_length (mux->sinks));
renatofilho@609
   371
        /* mark pad eos */
renatofilho@609
   372
        mux->sinks  = g_slist_remove (mux->sinks, pad);
renatofilho@609
   373
        g_debug ("sink len %d", g_slist_length (mux->sinks));
renatofilho@609
   374
        if (g_slist_length (mux->sinks) != 0) {
renatofilho@609
   375
           GMutex *mutex;
renatofilho@609
   376
           mux->sinkpad = mux->sinks->data;
renatofilho@609
   377
           mutex = (GMutex *) gst_pad_get_element_private (mux->sinkpad);
renatofilho@609
   378
           g_mutex_unlock (mutex);
renatofilho@609
   379
           g_debug ("sink pad %p", mux->sinkpad);
renatofilho@609
   380
           return TRUE;
renatofilho@609
   381
        }
renatofilho@609
   382
renatofilho@609
   383
        g_debug ("sink list is empty");
renatofilho@609
   384
    }
renatofilho@609
   385
    default:
renatofilho@609
   386
      break;
renatofilho@609
   387
  }
renatofilho@609
   388
renatofilho@609
   389
  gst_object_unref (mux);
renatofilho@609
   390
renatofilho@609
   391
  return gst_pad_event_default (pad, event);
renatofilho@609
   392
}
renatofilho@609
   393
renatofilho@609
   394
static GstFlowReturn
renatofilho@609
   395
gst_concat_mux_chain (GstPad * pad,  GstBuffer * buf)
renatofilho@609
   396
{
renatofilho@609
   397
  GstConcatMux *mux = (GstConcatMux *) GST_PAD_PARENT (pad);
renatofilho@609
   398
  GstBuffer *databuf = NULL;
renatofilho@609
   399
  GstFlowReturn ret = GST_FLOW_OK;
renatofilho@609
   400
  GMutex *mutex;
renatofilho@609
   401
renatofilho@609
   402
renatofilho@609
   403
  mutex = (GMutex*) gst_pad_get_element_private (pad);
renatofilho@609
   404
renatofilho@609
   405
  g_mutex_lock (mutex);
renatofilho@609
   406
  if (mux->done) {
renatofilho@609
   407
      g_debug ("DONE pad %p", pad);
renatofilho@620
   408
      g_mutex_unlock (mutex);
renatofilho@609
   409
      return GST_FLOW_OK;
renatofilho@609
   410
  }
renatofilho@609
   411
renatofilho@609
   412
  databuf = gst_buffer_make_metadata_writable (buf);
renatofilho@609
   413
renatofilho@609
   414
  if (!mux->negotiated) {
renatofilho@609
   415
      /*
renatofilho@609
   416
    GstCaps *newcaps;
renatofilho@609
   417
    newcaps = gst_pad_get_caps (mux->sinkpad);
renatofilho@609
   418
renatofilho@609
   419
    g_debug ("CAPS: %s",gst_caps_to_string (newcaps));
renatofilho@609
   420
renatofilho@609
   421
    if (!gst_pad_set_caps (mux->srcpad, newcaps))
renatofilho@609
   422
      goto nego_error;
renatofilho@609
   423
    */
renatofilho@609
   424
    mux->negotiated = TRUE;            
renatofilho@609
   425
  } 
renatofilho@609
   426
renatofilho@620
   427
  /*
renatofilho@609
   428
  g_debug ("Running [%s]\n"
renatofilho@609
   429
        "\tTOFFSET    [%"G_GUINT64_FORMAT"]\n"
renatofilho@609
   430
        "\tB_TSTAMP   [%"G_GUINT64_FORMAT"]\n"
renatofilho@609
   431
        "\tB_DURATION [%"G_GUINT64_FORMAT"]\n"
renatofilho@609
   432
        "\tOFFSET     [%"G_GUINT64_FORMAT"]\n"
renatofilho@609
   433
        "\tB_OFFSET   [%"G_GUINT64_FORMAT"]",
renatofilho@609
   434
        gst_element_get_name (mux),
renatofilho@609
   435
        mux->timeoffset, 
renatofilho@609
   436
        GST_BUFFER_TIMESTAMP (databuf),
renatofilho@609
   437
        GST_BUFFER_DURATION (databuf),
renatofilho@609
   438
        mux->offset,
renatofilho@609
   439
        GST_BUFFER_OFFSET (databuf));
renatofilho@620
   440
  */        
renatofilho@609
   441
renatofilho@609
   442
renatofilho@609
   443
  if (mux->resync) {
renatofilho@609
   444
    g_debug ("RESYNC [%s]", gst_element_get_name (mux));
renatofilho@609
   445
    mux->timeoffset += GST_BUFFER_TIMESTAMP (databuf);
renatofilho@609
   446
    GST_BUFFER_TIMESTAMP (databuf) = mux->timeoffset;
renatofilho@609
   447
    mux->timeoffset += GST_BUFFER_DURATION (databuf);
renatofilho@609
   448
renatofilho@609
   449
    mux->offset += GST_BUFFER_OFFSET (databuf);
renatofilho@609
   450
    GST_BUFFER_OFFSET (databuf) = mux->offset;
renatofilho@609
   451
    mux->offset += GST_BUFFER_SIZE (databuf);
renatofilho@609
   452
    mux->resync = FALSE;
renatofilho@609
   453
  } else {
renatofilho@609
   454
renatofilho@609
   455
    GST_BUFFER_TIMESTAMP (databuf) = mux->timeoffset;
renatofilho@609
   456
    mux->timeoffset += GST_BUFFER_DURATION (databuf);
renatofilho@609
   457
renatofilho@609
   458
    GST_BUFFER_OFFSET (databuf) = mux->offset;
renatofilho@609
   459
    mux->offset += GST_BUFFER_SIZE (databuf);
renatofilho@609
   460
  }
renatofilho@609
   461
renatofilho@609
   462
  gst_buffer_set_caps (databuf, GST_PAD_CAPS (pad));
renatofilho@609
   463
  ret = gst_pad_push (mux->srcpad, databuf);
renatofilho@609
   464
renatofilho@609
   465
  //gst_buffer_unref (buf);
renatofilho@609
   466
renatofilho@609
   467
  g_mutex_unlock (mutex);
renatofilho@609
   468
  return ret;
renatofilho@609
   469
/*
renatofilho@609
   470
nego_error:
renatofilho@609
   471
  {
renatofilho@609
   472
    GST_WARNING_OBJECT (mux, "failed to set caps");
renatofilho@609
   473
    GST_ELEMENT_ERROR (mux, CORE, NEGOTIATION, (NULL), (NULL));
renatofilho@609
   474
    return GST_FLOW_NOT_NEGOTIATED;
renatofilho@609
   475
  }
renatofilho@609
   476
  */
renatofilho@609
   477
  /*
renatofilho@609
   478
no_caps:
renatofilho@609
   479
  {
renatofilho@609
   480
    GST_WARNING_OBJECT (mux, "no caps on the incoming buffer %p", best->buffer);
renatofilho@609
   481
    GST_ELEMENT_ERROR (mux, CORE, NEGOTIATION, (NULL), (NULL));
renatofilho@609
   482
    ret = GST_FLOW_NOT_NEGOTIATED;
renatofilho@609
   483
    goto beach;
renatofilho@609
   484
  }
renatofilho@609
   485
  */
renatofilho@609
   486
}
renatofilho@609
   487
renatofilho@609
   488
static GstStateChangeReturn
renatofilho@609
   489
gst_concat_mux_change_state (GstElement * element, GstStateChange transition)
renatofilho@609
   490
{
renatofilho@609
   491
  GstConcatMux *concat_mux;
renatofilho@609
   492
  GstStateChangeReturn ret;
renatofilho@609
   493
renatofilho@609
   494
  concat_mux = GST_CONCAT_MUX (element);
renatofilho@609
   495
renatofilho@609
   496
  switch (transition) {
renatofilho@609
   497
    case GST_STATE_CHANGE_READY_TO_PAUSED:
renatofilho@609
   498
      concat_mux->done = FALSE;
renatofilho@609
   499
      concat_mux->resync = TRUE;
renatofilho@609
   500
      GST_DEBUG_OBJECT (concat_mux, "starting collect pads");
renatofilho@609
   501
      break;
renatofilho@609
   502
    case GST_STATE_CHANGE_PAUSED_TO_READY:
renatofilho@609
   503
      GST_DEBUG_OBJECT (concat_mux, "stopping collect pads");
renatofilho@609
   504
      gst_concat_mux_clear (concat_mux);
renatofilho@609
   505
      break;
renatofilho@609
   506
    default:
renatofilho@609
   507
      break;
renatofilho@609
   508
  }
renatofilho@609
   509
renatofilho@609
   510
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
renatofilho@609
   511
  if (ret == GST_STATE_CHANGE_FAILURE)
renatofilho@609
   512
    return ret;
renatofilho@609
   513
renatofilho@609
   514
  switch (transition) {
renatofilho@609
   515
    default:
renatofilho@609
   516
      break;
renatofilho@609
   517
  }
renatofilho@609
   518
renatofilho@609
   519
  return ret;
renatofilho@609
   520
}
renatofilho@609
   521
renatofilho@609
   522
gboolean
renatofilho@609
   523
gst_concat_mux_plugin_init (GstPlugin * plugin)
renatofilho@609
   524
{
renatofilho@609
   525
#ifdef ENABLE_NLS
renatofilho@609
   526
  setlocale (LC_ALL, "");
renatofilho@609
   527
  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
renatofilho@609
   528
#endif /* ENABLE_NLS */
renatofilho@609
   529
renatofilho@609
   530
  GST_DEBUG_CATEGORY_INIT (gst_concat_mux_debug, "concatmux", 0,
renatofilho@609
   531
      "concat muxer");
renatofilho@609
   532
      
renatofilho@609
   533
  return gst_element_register (plugin, "concatmux", GST_RANK_NONE,
renatofilho@609
   534
      GST_TYPE_CONCAT_MUX);
renatofilho@609
   535
}
renatofilho@609
   536
renatofilho@609
   537
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
renatofilho@609
   538
    GST_VERSION_MINOR,
renatofilho@620
   539
    "concatmux",
renatofilho@609
   540
    "Concat streamers",
renatofilho@611
   541
     gst_concat_mux_plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
renatofilho@609
   542