gst-gmyth/concatmux/gstconcatmux.c
author renatofilho
Thu Jun 14 18:22:32 2007 +0100 (2007-06-14)
branchtrunk
changeset 753 8ee634511c1e
parent 620 bc9827e02466
child 754 cb885ee44618
permissions -rw-r--r--
[svn r759] fixed indent using GNU Style
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@751
    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@751
    66
 /* Caps */
renatofilho@609
    67
  GstCaps *sink_caps;
renatofilho@609
    68
renatofilho@751
    69
 /* pad */
renatofilho@609
    70
  GstPad *srcpad;
renatofilho@609
    71
  GstPad *sinkpad;
renatofilho@609
    72
renatofilho@751
    73
 /* sinkpads */
renatofilho@609
    74
  GSList *sinks;
renatofilho@609
    75
  gint numpads;
renatofilho@609
    76
renatofilho@751
    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@751
    94
GST_ELEMENT_DETAILS("Concat muxer",
renatofilho@751
    95
					"Codec/Muxer",
renatofilho@751
    96
					"mux concat streams",
renatofilho@751
    97
					"Renato Filho <renato.filho@indt.org>");
renatofilho@609
    98
renatofilho@751
    99
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE("src",
renatofilho@751
   100
																  GST_PAD_SRC,
renatofilho@751
   101
																  GST_PAD_ALWAYS,
renatofilho@751
   102
																  GST_STATIC_CAPS_ANY);
renatofilho@609
   103
renatofilho@751
   104
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE("sink_%d",
renatofilho@751
   105
																   GST_PAD_SINK,
renatofilho@751
   106
																   GST_PAD_REQUEST,
renatofilho@751
   107
																   GST_STATIC_CAPS_ANY);
renatofilho@609
   108
renatofilho@751
   109
static void gst_concat_mux_base_init(gpointer g_class);
renatofilho@751
   110
static void gst_concat_mux_class_init(GstConcatMuxClass * klass);
renatofilho@751
   111
static void gst_concat_mux_init(GstConcatMux * concat_mux);
renatofilho@609
   112
renatofilho@751
   113
static void gst_concat_mux_finalize(GObject * object);
renatofilho@609
   114
renatofilho@751
   115
static gboolean gst_concat_mux_handle_src_event(GstPad * pad,
renatofilho@751
   116
												GstEvent * event);
renatofilho@751
   117
static gboolean gst_concat_mux_handle_sink_event(GstPad * pad,
renatofilho@751
   118
												 GstEvent * event);
renatofilho@609
   119
renatofilho@751
   120
static GstPad *gst_concat_mux_request_new_pad(GstElement * element,
renatofilho@751
   121
											  GstPadTemplate * templ,
renatofilho@751
   122
											  const gchar * name);
renatofilho@751
   123
static GstStateChangeReturn gst_concat_mux_change_state(GstElement * element,
renatofilho@751
   124
														GstStateChange
renatofilho@751
   125
														transition);
renatofilho@609
   126
renatofilho@751
   127
static GstFlowReturn gst_concat_mux_chain(GstPad * pad, GstBuffer * buf);
renatofilho@751
   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@751
   134
gst_concat_mux_get_type(void)
renatofilho@609
   135
{
renatofilho@609
   136
  static GType concat_mux_type = 0;
renatofilho@609
   137
renatofilho@751
   138
  if (!concat_mux_type)
renatofilho@751
   139
	{
renatofilho@751
   140
	  static const GTypeInfo concat_mux_info = {
renatofilho@751
   141
		sizeof(GstConcatMuxClass),
renatofilho@751
   142
		gst_concat_mux_base_init,
renatofilho@751
   143
		NULL,
renatofilho@751
   144
		(GClassInitFunc) gst_concat_mux_class_init,
renatofilho@751
   145
		NULL,
renatofilho@751
   146
		NULL,
renatofilho@751
   147
		sizeof(GstConcatMux),
renatofilho@751
   148
		0,
renatofilho@751
   149
		(GInstanceInitFunc) gst_concat_mux_init,
renatofilho@751
   150
	  };
renatofilho@609
   151
renatofilho@751
   152
	  concat_mux_type =
renatofilho@751
   153
		g_type_register_static(GST_TYPE_ELEMENT, "GstConcatMux",
renatofilho@751
   154
							   &concat_mux_info, 0);
renatofilho@751
   155
	}
renatofilho@609
   156
  return concat_mux_type;
renatofilho@609
   157
}
renatofilho@609
   158
renatofilho@609
   159
static void
renatofilho@751
   160
gst_concat_mux_base_init(gpointer g_class)
renatofilho@609
   161
{
renatofilho@751
   162
  GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
renatofilho@609
   163
renatofilho@751
   164
  gst_element_class_add_pad_template(element_class,
renatofilho@751
   165
									 gst_static_pad_template_get
renatofilho@751
   166
									 (&src_factory));
renatofilho@751
   167
  gst_element_class_add_pad_template(element_class,
renatofilho@751
   168
									 gst_static_pad_template_get
renatofilho@751
   169
									 (&sink_factory));
renatofilho@609
   170
renatofilho@751
   171
  gst_element_class_set_details(element_class, &gst_concat_mux_details);
renatofilho@609
   172
}
renatofilho@609
   173
renatofilho@609
   174
static void
renatofilho@751
   175
gst_concat_mux_class_init(GstConcatMuxClass * klass)
renatofilho@609
   176
{
renatofilho@609
   177
  GObjectClass *gobject_class;
renatofilho@609
   178
  GstElementClass *gstelement_class;
renatofilho@609
   179
renatofilho@609
   180
  gobject_class = (GObjectClass *) klass;
renatofilho@609
   181
  gstelement_class = (GstElementClass *) klass;
renatofilho@609
   182
renatofilho@751
   183
  parent_class = g_type_class_peek_parent(klass);
renatofilho@609
   184
renatofilho@609
   185
  gobject_class->finalize = gst_concat_mux_finalize;
renatofilho@609
   186
renatofilho@609
   187
  gstelement_class->request_new_pad = gst_concat_mux_request_new_pad;
renatofilho@609
   188
  gstelement_class->change_state = gst_concat_mux_change_state;
renatofilho@609
   189
}
renatofilho@609
   190
renatofilho@609
   191
static void
renatofilho@751
   192
gst_concat_mux_init(GstConcatMux * concat_mux)
renatofilho@609
   193
{
renatofilho@751
   194
  GstElementClass *klass = GST_ELEMENT_GET_CLASS(concat_mux);
renatofilho@609
   195
renatofilho@609
   196
  concat_mux->srcpad =
renatofilho@751
   197
	gst_pad_new_from_template(gst_element_class_get_pad_template(klass,
renatofilho@751
   198
																 "src"),
renatofilho@751
   199
							  "src");
renatofilho@751
   200
  gst_pad_set_event_function(concat_mux->srcpad,
renatofilho@751
   201
							 gst_concat_mux_handle_src_event);
renatofilho@751
   202
  gst_element_add_pad(GST_ELEMENT(concat_mux), concat_mux->srcpad);
renatofilho@609
   203
}
renatofilho@609
   204
renatofilho@609
   205
static void
renatofilho@751
   206
gst_concat_mux_finalize(GObject * object)
renatofilho@609
   207
{
renatofilho@609
   208
  GstConcatMux *concat_mux;
renatofilho@609
   209
renatofilho@751
   210
  concat_mux = GST_CONCAT_MUX(object);
renatofilho@751
   211
  gst_concat_mux_clear(GST_CONCAT_MUX(object));
renatofilho@609
   212
renatofilho@751
   213
  G_OBJECT_CLASS(parent_class)->finalize(object);
renatofilho@609
   214
}
renatofilho@609
   215
renatofilho@609
   216
static void
renatofilho@751
   217
gst_concat_mux_free_pad(gpointer data, gpointer user_data)
renatofilho@609
   218
{
renatofilho@751
   219
  GMutex *mux;
renatofilho@609
   220
renatofilho@751
   221
  mux = gst_pad_get_element_private(GST_PAD(data));
renatofilho@751
   222
  g_mutex_unlock(mux);
renatofilho@751
   223
  g_mutex_free(mux);
renatofilho@751
   224
  gst_object_unref(GST_OBJECT(data));
renatofilho@609
   225
}
renatofilho@609
   226
renatofilho@609
   227
static void
renatofilho@751
   228
gst_concat_mux_clear(GstConcatMux * mux)
renatofilho@609
   229
{
renatofilho@609
   230
  mux->resync = TRUE;
renatofilho@609
   231
  mux->timeoffset = 0;
renatofilho@609
   232
  mux->offset = 0;
renatofilho@609
   233
  mux->negotiated = FALSE;
renatofilho@609
   234
  mux->done = TRUE;
renatofilho@751
   235
  if (mux->sinks != NULL)
renatofilho@751
   236
	{
renatofilho@751
   237
	  g_slist_foreach(mux->sinks, gst_concat_mux_free_pad, mux);
renatofilho@751
   238
	  g_slist_free(mux->sinks);
renatofilho@751
   239
	  mux->sinks = NULL;
renatofilho@751
   240
	}
renatofilho@609
   241
}
renatofilho@609
   242
renatofilho@609
   243
renatofilho@609
   244
static GstPadLinkReturn
renatofilho@751
   245
gst_concat_mux_sinkconnect(GstPad * pad, GstPad * peer)
renatofilho@609
   246
{
renatofilho@609
   247
  gchar *pad_name = NULL;
renatofilho@609
   248
  GstConcatMux *concat_mux;
renatofilho@609
   249
renatofilho@751
   250
  concat_mux = GST_CONCAT_MUX(gst_pad_get_parent(pad));
renatofilho@609
   251
renatofilho@751
   252
  if (concat_mux->sink_caps != NULL)
renatofilho@751
   253
	{
renatofilho@751
   254
	  GstCaps *peer_caps = gst_pad_get_caps(peer);
renatofilho@751
   255
	  GstCaps *intersect;
renatofilho@609
   256
renatofilho@751
   257
	  intersect = gst_caps_intersect(concat_mux->sink_caps, peer_caps);
renatofilho@751
   258
	  if (intersect == NULL)
renatofilho@751
   259
		{
renatofilho@751
   260
		  gst_caps_unref(peer_caps);
renatofilho@751
   261
		  return GST_PAD_LINK_NOFORMAT;
renatofilho@751
   262
		}
renatofilho@751
   263
	  gst_caps_unref(peer_caps);
renatofilho@751
   264
	  gst_caps_unref(intersect);
renatofilho@751
   265
	}
renatofilho@751
   266
  else
renatofilho@751
   267
	{
renatofilho@751
   268
	  concat_mux->sink_caps = gst_pad_get_caps(pad);
renatofilho@751
   269
	}
renatofilho@609
   270
renatofilho@751
   271
  pad_name = gst_pad_get_name(pad);
renatofilho@609
   272
renatofilho@751
   273
  GST_DEBUG_OBJECT(concat_mux, "sinkconnect triggered on %s", pad_name);
renatofilho@609
   274
renatofilho@751
   275
  g_free(pad_name);
renatofilho@609
   276
renatofilho@751
   277
  gst_object_unref(concat_mux);
renatofilho@609
   278
renatofilho@609
   279
  return GST_PAD_LINK_OK;
renatofilho@609
   280
}
renatofilho@609
   281
renatofilho@609
   282
static GstPad *
renatofilho@751
   283
gst_concat_mux_request_new_pad(GstElement * element,
renatofilho@751
   284
							   GstPadTemplate * templ, const gchar * req_name)
renatofilho@609
   285
{
renatofilho@609
   286
  GstConcatMux *concat_mux;
renatofilho@609
   287
  GstPad *newpad;
renatofilho@751
   288
  GstElementClass *klass = GST_ELEMENT_GET_CLASS(element);
renatofilho@609
   289
  GMutex *mutex;
renatofilho@609
   290
renatofilho@751
   291
  g_return_val_if_fail(templ != NULL, NULL);
renatofilho@609
   292
renatofilho@751
   293
  if (templ->direction != GST_PAD_SINK)
renatofilho@751
   294
	{
renatofilho@751
   295
	  g_warning("concat_mux: request pad that is not a SINK pad\n");
renatofilho@751
   296
	  return NULL;
renatofilho@751
   297
	}
renatofilho@609
   298
renatofilho@751
   299
  g_return_val_if_fail(GST_IS_CONCAT_MUX(element), NULL);
renatofilho@609
   300
renatofilho@751
   301
  concat_mux = GST_CONCAT_MUX(element);
renatofilho@609
   302
renatofilho@751
   303
  if (templ == gst_element_class_get_pad_template(klass, "sink_%d"))
renatofilho@751
   304
	{
renatofilho@751
   305
	  gchar *name;
renatofilho@609
   306
renatofilho@751
   307
	 /* create new pad with the name */
renatofilho@751
   308
	  name = g_strdup_printf("sink_%02d", concat_mux->numpads);
renatofilho@751
   309
	  g_debug("NEw pad %s", name);
renatofilho@751
   310
	  newpad = gst_pad_new_from_template(templ, name);
renatofilho@751
   311
	  g_free(name);
renatofilho@751
   312
	  concat_mux->sinks = g_slist_append(concat_mux->sinks, newpad);
renatofilho@751
   313
	  g_debug("New sink %p / %d", newpad, g_slist_length(concat_mux->sinks));
renatofilho@751
   314
	  concat_mux->numpads++;
renatofilho@751
   315
	}
renatofilho@751
   316
  else
renatofilho@751
   317
	{
renatofilho@751
   318
	  g_warning("concat_mux: this is not our template!\n");
renatofilho@751
   319
	  return NULL;
renatofilho@751
   320
	}
renatofilho@609
   321
renatofilho@751
   322
  mutex = g_mutex_new();
renatofilho@609
   323
renatofilho@751
   324
  if (concat_mux->sinkpad == NULL)
renatofilho@751
   325
	{
renatofilho@751
   326
	  concat_mux->sinkpad = newpad;
renatofilho@751
   327
	}
renatofilho@751
   328
  else
renatofilho@751
   329
	{
renatofilho@751
   330
	  g_mutex_lock(mutex);
renatofilho@751
   331
	}
renatofilho@609
   332
renatofilho@751
   333
  gst_pad_set_element_private(newpad, mutex);
renatofilho@751
   334
 /* setup some pad functions */
renatofilho@751
   335
  gst_pad_set_link_function(newpad, gst_concat_mux_sinkconnect);
renatofilho@751
   336
  gst_pad_set_event_function(newpad, gst_concat_mux_handle_sink_event);
renatofilho@751
   337
  gst_pad_set_chain_function(newpad, gst_concat_mux_chain);
renatofilho@609
   338
renatofilho@751
   339
 /* add the pad to the element */
renatofilho@751
   340
  gst_element_add_pad(element, newpad);
renatofilho@609
   341
renatofilho@609
   342
  return newpad;
renatofilho@609
   343
}
renatofilho@609
   344
renatofilho@609
   345
/* handle events */
renatofilho@609
   346
static gboolean
renatofilho@751
   347
gst_concat_mux_handle_src_event(GstPad * pad, GstEvent * event)
renatofilho@609
   348
{
renatofilho@609
   349
  GstConcatMux *concat_mux;
renatofilho@609
   350
  GstEventType type;
renatofilho@609
   351
renatofilho@751
   352
  concat_mux = GST_CONCAT_MUX(gst_pad_get_parent(pad));
renatofilho@609
   353
renatofilho@751
   354
  type = event ? GST_EVENT_TYPE(event) : GST_EVENT_UNKNOWN;
renatofilho@609
   355
renatofilho@751
   356
  switch (type)
renatofilho@751
   357
	{
renatofilho@751
   358
	case GST_EVENT_SEEK:
renatofilho@751
   359
	 /* disable seeking for now */
renatofilho@751
   360
	  return FALSE;
renatofilho@751
   361
	default:
renatofilho@751
   362
	  break;
renatofilho@751
   363
	}
renatofilho@609
   364
renatofilho@751
   365
  gst_object_unref(concat_mux);
renatofilho@609
   366
renatofilho@751
   367
  return gst_pad_event_default(pad, event);
renatofilho@609
   368
}
renatofilho@609
   369
renatofilho@609
   370
/* handle events */
renatofilho@609
   371
static gboolean
renatofilho@751
   372
gst_concat_mux_handle_sink_event(GstPad * pad, GstEvent * event)
renatofilho@609
   373
{
renatofilho@609
   374
  GstConcatMux *mux;
renatofilho@609
   375
  GstEventType type;
renatofilho@609
   376
renatofilho@751
   377
  mux = GST_CONCAT_MUX(gst_pad_get_parent(pad));
renatofilho@609
   378
renatofilho@751
   379
  type = event ? GST_EVENT_TYPE(event) : GST_EVENT_UNKNOWN;
renatofilho@609
   380
renatofilho@751
   381
  switch (type)
renatofilho@751
   382
	{
renatofilho@751
   383
	case GST_EVENT_EOS:
renatofilho@751
   384
	  {
renatofilho@751
   385
		mux->resync = TRUE;
renatofilho@751
   386
		g_debug("sink EOS %p / %d", pad, g_slist_length(mux->sinks));
renatofilho@751
   387
	   /* mark pad eos */
renatofilho@751
   388
		mux->sinks = g_slist_remove(mux->sinks, pad);
renatofilho@751
   389
		g_debug("sink len %d", g_slist_length(mux->sinks));
renatofilho@751
   390
		if (g_slist_length(mux->sinks) != 0)
renatofilho@751
   391
		  {
renatofilho@751
   392
			GMutex *mutex;
renatofilho@751
   393
			mux->sinkpad = mux->sinks->data;
renatofilho@751
   394
			mutex = (GMutex *) gst_pad_get_element_private(mux->sinkpad);
renatofilho@751
   395
			g_mutex_unlock(mutex);
renatofilho@751
   396
			g_debug("sink pad %p", mux->sinkpad);
renatofilho@751
   397
			return TRUE;
renatofilho@751
   398
		  }
renatofilho@609
   399
renatofilho@751
   400
		g_debug("sink list is empty");
renatofilho@751
   401
	  }
renatofilho@751
   402
	default:
renatofilho@751
   403
	  break;
renatofilho@751
   404
	}
renatofilho@609
   405
renatofilho@751
   406
  gst_object_unref(mux);
renatofilho@609
   407
renatofilho@751
   408
  return gst_pad_event_default(pad, event);
renatofilho@609
   409
}
renatofilho@609
   410
renatofilho@609
   411
static GstFlowReturn
renatofilho@751
   412
gst_concat_mux_chain(GstPad * pad, GstBuffer * buf)
renatofilho@609
   413
{
renatofilho@751
   414
  GstConcatMux *mux = (GstConcatMux *) GST_PAD_PARENT(pad);
renatofilho@609
   415
  GstBuffer *databuf = NULL;
renatofilho@609
   416
  GstFlowReturn ret = GST_FLOW_OK;
renatofilho@609
   417
  GMutex *mutex;
renatofilho@609
   418
renatofilho@609
   419
renatofilho@751
   420
  mutex = (GMutex *) gst_pad_get_element_private(pad);
renatofilho@609
   421
renatofilho@751
   422
  g_mutex_lock(mutex);
renatofilho@751
   423
  if (mux->done)
renatofilho@751
   424
	{
renatofilho@751
   425
	  g_debug("DONE pad %p", pad);
renatofilho@751
   426
	  g_mutex_unlock(mutex);
renatofilho@751
   427
	  return GST_FLOW_OK;
renatofilho@751
   428
	}
renatofilho@609
   429
renatofilho@751
   430
  databuf = gst_buffer_make_metadata_writable(buf);
renatofilho@609
   431
renatofilho@751
   432
  if (!mux->negotiated)
renatofilho@751
   433
	{
renatofilho@751
   434
	 /*
renatofilho@751
   435
	    GstCaps *newcaps;
renatofilho@751
   436
	    newcaps = gst_pad_get_caps (mux->sinkpad);
renatofilho@609
   437
renatofilho@751
   438
	    g_debug ("CAPS: %s",gst_caps_to_string (newcaps));
renatofilho@609
   439
renatofilho@751
   440
	    if (!gst_pad_set_caps (mux->srcpad, newcaps))
renatofilho@751
   441
	    goto nego_error;
renatofilho@751
   442
	  */
renatofilho@751
   443
	  mux->negotiated = TRUE;
renatofilho@751
   444
	}
renatofilho@609
   445
renatofilho@751
   446
 /*
renatofilho@751
   447
    g_debug ("Running [%s]\n"
renatofilho@751
   448
    "\tTOFFSET    [%"G_GUINT64_FORMAT"]\n"
renatofilho@751
   449
    "\tB_TSTAMP   [%"G_GUINT64_FORMAT"]\n"
renatofilho@751
   450
    "\tB_DURATION [%"G_GUINT64_FORMAT"]\n"
renatofilho@751
   451
    "\tOFFSET     [%"G_GUINT64_FORMAT"]\n"
renatofilho@751
   452
    "\tB_OFFSET   [%"G_GUINT64_FORMAT"]",
renatofilho@751
   453
    gst_element_get_name (mux),
renatofilho@751
   454
    mux->timeoffset, 
renatofilho@751
   455
    GST_BUFFER_TIMESTAMP (databuf),
renatofilho@751
   456
    GST_BUFFER_DURATION (databuf),
renatofilho@751
   457
    mux->offset,
renatofilho@751
   458
    GST_BUFFER_OFFSET (databuf));
renatofilho@751
   459
  */
renatofilho@609
   460
renatofilho@609
   461
renatofilho@751
   462
  if (mux->resync)
renatofilho@751
   463
	{
renatofilho@751
   464
	  g_debug("RESYNC [%s]", gst_element_get_name(mux));
renatofilho@751
   465
	  mux->timeoffset += GST_BUFFER_TIMESTAMP(databuf);
renatofilho@751
   466
	  GST_BUFFER_TIMESTAMP(databuf) = mux->timeoffset;
renatofilho@751
   467
	  mux->timeoffset += GST_BUFFER_DURATION(databuf);
renatofilho@609
   468
renatofilho@751
   469
	  mux->offset += GST_BUFFER_OFFSET(databuf);
renatofilho@751
   470
	  GST_BUFFER_OFFSET(databuf) = mux->offset;
renatofilho@751
   471
	  mux->offset += GST_BUFFER_SIZE(databuf);
renatofilho@751
   472
	  mux->resync = FALSE;
renatofilho@751
   473
	}
renatofilho@751
   474
  else
renatofilho@751
   475
	{
renatofilho@609
   476
renatofilho@751
   477
	  GST_BUFFER_TIMESTAMP(databuf) = mux->timeoffset;
renatofilho@751
   478
	  mux->timeoffset += GST_BUFFER_DURATION(databuf);
renatofilho@609
   479
renatofilho@751
   480
	  GST_BUFFER_OFFSET(databuf) = mux->offset;
renatofilho@751
   481
	  mux->offset += GST_BUFFER_SIZE(databuf);
renatofilho@751
   482
	}
renatofilho@609
   483
renatofilho@751
   484
  gst_buffer_set_caps(databuf, GST_PAD_CAPS(pad));
renatofilho@751
   485
  ret = gst_pad_push(mux->srcpad, databuf);
renatofilho@609
   486
renatofilho@751
   487
 //gst_buffer_unref (buf);
renatofilho@609
   488
renatofilho@751
   489
  g_mutex_unlock(mutex);
renatofilho@609
   490
  return ret;
renatofilho@609
   491
/*
renatofilho@609
   492
nego_error:
renatofilho@609
   493
  {
renatofilho@609
   494
    GST_WARNING_OBJECT (mux, "failed to set caps");
renatofilho@609
   495
    GST_ELEMENT_ERROR (mux, CORE, NEGOTIATION, (NULL), (NULL));
renatofilho@609
   496
    return GST_FLOW_NOT_NEGOTIATED;
renatofilho@609
   497
  }
renatofilho@609
   498
  */
renatofilho@751
   499
 /*
renatofilho@751
   500
    no_caps:
renatofilho@751
   501
    {
renatofilho@609
   502
    GST_WARNING_OBJECT (mux, "no caps on the incoming buffer %p", best->buffer);
renatofilho@609
   503
    GST_ELEMENT_ERROR (mux, CORE, NEGOTIATION, (NULL), (NULL));
renatofilho@609
   504
    ret = GST_FLOW_NOT_NEGOTIATED;
renatofilho@609
   505
    goto beach;
renatofilho@751
   506
    }
renatofilho@609
   507
  */
renatofilho@609
   508
}
renatofilho@609
   509
renatofilho@609
   510
static GstStateChangeReturn
renatofilho@751
   511
gst_concat_mux_change_state(GstElement * element, GstStateChange transition)
renatofilho@609
   512
{
renatofilho@609
   513
  GstConcatMux *concat_mux;
renatofilho@609
   514
  GstStateChangeReturn ret;
renatofilho@609
   515
renatofilho@751
   516
  concat_mux = GST_CONCAT_MUX(element);
renatofilho@609
   517
renatofilho@751
   518
  switch (transition)
renatofilho@751
   519
	{
renatofilho@751
   520
	case GST_STATE_CHANGE_READY_TO_PAUSED:
renatofilho@751
   521
	  concat_mux->done = FALSE;
renatofilho@751
   522
	  concat_mux->resync = TRUE;
renatofilho@751
   523
	  GST_DEBUG_OBJECT(concat_mux, "starting collect pads");
renatofilho@751
   524
	  break;
renatofilho@751
   525
	case GST_STATE_CHANGE_PAUSED_TO_READY:
renatofilho@751
   526
	  GST_DEBUG_OBJECT(concat_mux, "stopping collect pads");
renatofilho@751
   527
	  gst_concat_mux_clear(concat_mux);
renatofilho@751
   528
	  break;
renatofilho@751
   529
	default:
renatofilho@751
   530
	  break;
renatofilho@751
   531
	}
renatofilho@609
   532
renatofilho@751
   533
  ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
renatofilho@609
   534
  if (ret == GST_STATE_CHANGE_FAILURE)
renatofilho@751
   535
	return ret;
renatofilho@609
   536
renatofilho@751
   537
  switch (transition)
renatofilho@751
   538
	{
renatofilho@751
   539
	default:
renatofilho@751
   540
	  break;
renatofilho@751
   541
	}
renatofilho@609
   542
renatofilho@609
   543
  return ret;
renatofilho@609
   544
}
renatofilho@609
   545
renatofilho@609
   546
gboolean
renatofilho@751
   547
gst_concat_mux_plugin_init(GstPlugin * plugin)
renatofilho@609
   548
{
renatofilho@609
   549
#ifdef ENABLE_NLS
renatofilho@751
   550
  setlocale(LC_ALL, "");
renatofilho@751
   551
  bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
renatofilho@609
   552
#endif /* ENABLE_NLS */
renatofilho@609
   553
renatofilho@751
   554
  GST_DEBUG_CATEGORY_INIT(gst_concat_mux_debug, "concatmux", 0,
renatofilho@751
   555
						  "concat muxer");
renatofilho@751
   556
renatofilho@751
   557
  return gst_element_register(plugin, "concatmux", GST_RANK_NONE,
renatofilho@751
   558
							  GST_TYPE_CONCAT_MUX);
renatofilho@609
   559
}
renatofilho@609
   560
renatofilho@751
   561
GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
renatofilho@751
   562
				  GST_VERSION_MINOR,
renatofilho@751
   563
				  "concatmux",
renatofilho@751
   564
				  "Concat streamers",
renatofilho@751
   565
				  gst_concat_mux_plugin_init, VERSION, GST_LICENSE,
renatofilho@751
   566
				  GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)