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