1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gst-gpac/src/gpacmux.c Thu Feb 21 17:54:48 2008 +0000
1.3 @@ -0,0 +1,604 @@
1.4 +
1.5 +#ifdef HAVE_CONFIG_H
1.6 +#include "config.h"
1.7 +#endif
1.8 +
1.9 +#include <gst/gst.h>
1.10 +#include <gst/base/gstcollectpads.h>
1.11 +
1.12 +#include <stdlib.h>
1.13 +#include <string.h>
1.14 +
1.15 +/* gpac includes */
1.16 +#include <gpac/isomedia.h>
1.17 +
1.18 +#define GST_TYPE_GPAC_MUX (gst_gpac_mux_get_type())
1.19 +#define GST_GPAC_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GPAC_MUX, GstGpacMux))
1.20 +#define GST_GPAC_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GPAC_MUX, GstGpacMux))
1.21 +#define GST_IS_GPAC_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GPAC_MUX))
1.22 +#define GST_IS_GPAC_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GPAC_MUX))
1.23 +
1.24 +typedef struct _GstGpacMux GstGpacMux;
1.25 +typedef struct _GstGpacMuxClass GstGpacMuxClass;
1.26 +
1.27 +typedef enum
1.28 +{
1.29 + GST_GPAC_PAD_STATE_CONTROL = 0,
1.30 + GST_GPAC_PAD_STATE_DATA = 1
1.31 +}
1.32 +GstGpacPadState;
1.33 +
1.34 +typedef struct
1.35 +{
1.36 + GstCollectData collect; /* we extend the CollectData */
1.37 +
1.38 + gint track_number;
1.39 + guint32 di; /* outDescriptionIndex */
1.40 +
1.41 + guint32 frame_count;
1.42 + gboolean is_video;
1.43 +
1.44 +} GstGpacPad;
1.45 +
1.46 +struct _GstGpacMux
1.47 +{
1.48 + GstElement element;
1.49 +
1.50 + GstPad *srcpad;
1.51 + GstCollectPads *collect;
1.52 +
1.53 + GF_ISOFile *file;
1.54 +
1.55 +};
1.56 +
1.57 +struct _GstGpacMuxClass
1.58 +{
1.59 + GstElementClass parent_class;
1.60 +};
1.61 +
1.62 +/* elementfactory information */
1.63 +static const GstElementDetails gst_gpac_mux_details =
1.64 +GST_ELEMENT_DETAILS ("Gpac muxer",
1.65 + "Codec/Muxer",
1.66 + "mux mp4 streams",
1.67 + "Hallyson Melo <hallyson.melo@indt.org.br");
1.68 +
1.69 +/* GpacMux signals and args */
1.70 +enum
1.71 +{
1.72 + /* FILL ME */
1.73 + LAST_SIGNAL
1.74 +};
1.75 +
1.76 +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
1.77 + GST_PAD_SRC,
1.78 + GST_PAD_ALWAYS,
1.79 + GST_STATIC_CAPS ("video/quicktime")
1.80 + );
1.81 +
1.82 +static GstStaticPadTemplate audio_sink_factory = GST_STATIC_PAD_TEMPLATE ("audio_%d",
1.83 + GST_PAD_SINK,
1.84 + GST_PAD_REQUEST,
1.85 + GST_STATIC_CAPS (
1.86 + "audio/mpeg, "
1.87 + "mpegversion = (int) 4, "
1.88 + "channels = (int) { 1, 2 }, "
1.89 + "rate = (int) [ 8000, 96000 ]")
1.90 + );
1.91 + //GST_STATIC_CAPS ("audio/mpeg, mpegversion = 1, layer = 3")
1.92 +
1.93 +static GstStaticPadTemplate video_sink_factory = GST_STATIC_PAD_TEMPLATE ("video_%d",
1.94 + GST_PAD_SINK,
1.95 + GST_PAD_REQUEST,
1.96 + GST_STATIC_CAPS ("video/mpeg, mpegversion = 4")
1.97 + );
1.98 +
1.99 +static void gst_gpac_mux_base_init (gpointer g_class);
1.100 +static void gst_gpac_mux_class_init (GstGpacMuxClass * klass);
1.101 +static void gst_gpac_mux_init (GstGpacMux * gpac_mux);
1.102 +static void gst_gpac_mux_finalize (GObject * object);
1.103 +
1.104 +static GstFlowReturn
1.105 +gst_gpac_mux_collected (GstCollectPads * pads, GstGpacMux * gpac_mux);
1.106 +
1.107 +static gboolean gst_gpac_mux_handle_src_event (GstPad * pad, GstEvent * event);
1.108 +static GstPad *gst_gpac_mux_request_new_pad (GstElement * element,
1.109 + GstPadTemplate * templ, const gchar * name);
1.110 +static void gst_gpac_mux_release_pad (GstElement * element, GstPad * pad);
1.111 +
1.112 +static GstStateChangeReturn gst_gpac_mux_change_state (GstElement * element,
1.113 + GstStateChange transition);
1.114 +
1.115 +static GstElementClass *parent_class = NULL;
1.116 +
1.117 +GType
1.118 +gst_gpac_mux_get_type (void)
1.119 +{
1.120 + static GType gpac_mux_type = 0;
1.121 +
1.122 + if (G_UNLIKELY (gpac_mux_type == 0)) {
1.123 + static const GTypeInfo gpac_mux_info = {
1.124 + sizeof (GstGpacMuxClass),
1.125 + gst_gpac_mux_base_init,
1.126 + NULL,
1.127 + (GClassInitFunc) gst_gpac_mux_class_init,
1.128 + NULL,
1.129 + NULL,
1.130 + sizeof (GstGpacMux),
1.131 + 0,
1.132 + (GInstanceInitFunc) gst_gpac_mux_init,
1.133 + };
1.134 +
1.135 + gpac_mux_type =
1.136 + g_type_register_static (GST_TYPE_ELEMENT, "GstGpacMux", &gpac_mux_info,
1.137 + 0);
1.138 + }
1.139 + return gpac_mux_type;
1.140 +}
1.141 +
1.142 +static void
1.143 +gst_gpac_mux_base_init (gpointer g_class)
1.144 +{
1.145 + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1.146 +
1.147 + gst_element_class_add_pad_template (element_class,
1.148 + gst_static_pad_template_get (&src_factory));
1.149 + gst_element_class_add_pad_template (element_class,
1.150 + gst_static_pad_template_get (&audio_sink_factory));
1.151 + gst_element_class_add_pad_template (element_class,
1.152 + gst_static_pad_template_get (&video_sink_factory));
1.153 +
1.154 + gst_element_class_set_details (element_class, &gst_gpac_mux_details);
1.155 +}
1.156 +
1.157 +static void
1.158 +gst_gpac_mux_class_init (GstGpacMuxClass * klass)
1.159 +{
1.160 + GObjectClass *gobject_class;
1.161 + GstElementClass *gstelement_class;
1.162 +
1.163 + gobject_class = (GObjectClass *) klass;
1.164 + gstelement_class = (GstElementClass *) klass;
1.165 +
1.166 + parent_class = g_type_class_peek_parent (klass);
1.167 +
1.168 + gobject_class->finalize = gst_gpac_mux_finalize;
1.169 +
1.170 + gstelement_class->request_new_pad = gst_gpac_mux_request_new_pad;
1.171 + gstelement_class->release_pad = gst_gpac_mux_release_pad;
1.172 +
1.173 + gstelement_class->change_state = gst_gpac_mux_change_state;
1.174 +
1.175 +}
1.176 +
1.177 +static void
1.178 +gst_gpac_mux_init (GstGpacMux * gpac_mux)
1.179 +{
1.180 + GstElementClass *klass = GST_ELEMENT_GET_CLASS (gpac_mux);
1.181 +
1.182 + gpac_mux->srcpad =
1.183 + gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
1.184 + "src"), "src");
1.185 + gst_pad_set_event_function (gpac_mux->srcpad, gst_gpac_mux_handle_src_event);
1.186 + gst_element_add_pad (GST_ELEMENT (gpac_mux), gpac_mux->srcpad);
1.187 +
1.188 + gpac_mux->collect = gst_collect_pads_new ();
1.189 + gst_collect_pads_set_function (gpac_mux->collect,
1.190 + (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_gpac_mux_collected),
1.191 + gpac_mux);
1.192 +
1.193 + /* Opens gpac library */
1.194 + /* FIXME */
1.195 + gpac_mux->file = gf_isom_open("/tmp/gpac.mp4", GF_ISOM_OPEN_WRITE, NULL);
1.196 + gf_isom_set_storage_mode(gpac_mux->file, GF_ISOM_STORE_FLAT /*STREAMABLE*/);
1.197 +
1.198 + //gst_gpac_mux_clear (gpac_mux);
1.199 +}
1.200 +
1.201 +static void
1.202 +gst_gpac_mux_finalize (GObject * object)
1.203 +{
1.204 + GstGpacMux *gpac_mux;
1.205 +
1.206 + gpac_mux = GST_GPAC_MUX (object);
1.207 +
1.208 + if (gpac_mux->collect) {
1.209 + gst_object_unref (gpac_mux->collect);
1.210 + gpac_mux->collect = NULL;
1.211 + }
1.212 +
1.213 + G_OBJECT_CLASS (parent_class)->finalize (object);
1.214 +}
1.215 +
1.216 +static void
1.217 +gst_gpac_mux_gpac_pad_destroy_notify (GstCollectData * data)
1.218 +{
1.219 + GstGpacPad *gpacpad = (GstGpacPad *) data;
1.220 + GstBuffer *buf;
1.221 +
1.222 +/* if (gpacpad->pagebuffers) {
1.223 + while ((buf = g_queue_pop_head (gpacpad->pagebuffers)) != NULL) {
1.224 + gst_buffer_unref (buf);
1.225 + }
1.226 + g_queue_free (gpacpad->pagebuffers);
1.227 + gpacpad->pagebuffers = NULL;
1.228 + }*/
1.229 +}
1.230 +
1.231 +static GstPadLinkReturn
1.232 +gst_gpac_mux_sinkconnect (GstPad * pad, GstPad * peer)
1.233 +{
1.234 + GstGpacMux *gpac_mux;
1.235 +
1.236 + gpac_mux = GST_GPAC_MUX (gst_pad_get_parent (pad));
1.237 +
1.238 + GST_DEBUG_OBJECT (gpac_mux, "sinkconnect triggered on %s", GST_PAD_NAME (pad));
1.239 +
1.240 + gst_object_unref (gpac_mux);
1.241 +
1.242 + return GST_PAD_LINK_OK;
1.243 +}
1.244 +
1.245 +static GstPad *
1.246 +gst_gpac_mux_request_new_pad (GstElement * element,
1.247 + GstPadTemplate * templ, const gchar * req_name)
1.248 +{
1.249 + GstGpacMux *gpac_mux;
1.250 + GstPad *newpad;
1.251 + GstElementClass *klass;
1.252 + gchar *padname = NULL;
1.253 + gint serial;
1.254 + gboolean is_video = FALSE;
1.255 +
1.256 + g_return_val_if_fail (templ != NULL, NULL);
1.257 +
1.258 + if (templ->direction != GST_PAD_SINK)
1.259 + goto wrong_direction;
1.260 +
1.261 + g_return_val_if_fail (GST_IS_GPAC_MUX (element), NULL);
1.262 + gpac_mux = GST_GPAC_MUX (element);
1.263 +
1.264 + klass = GST_ELEMENT_GET_CLASS (element);
1.265 +
1.266 + if (req_name == NULL || strlen (req_name) < 6) {
1.267 + /* no name given when requesting the pad, use random serial number */
1.268 + serial = rand ();
1.269 + } else {
1.270 + /* parse serial number from requested padname */
1.271 + serial = atoi (&req_name[5]);
1.272 + }
1.273 +
1.274 + if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
1.275 + is_video = TRUE;
1.276 + padname = g_strdup_printf ("video_%d", serial);
1.277 + } else if (templ != gst_element_class_get_pad_template (klass, "audio_%d")) {
1.278 + goto wrong_template;
1.279 + } else {
1.280 + padname = g_strdup_printf ("audio_%d", serial);
1.281 + }
1.282 +
1.283 +
1.284 + {
1.285 +
1.286 + /* create new pad with the name */
1.287 + GST_DEBUG_OBJECT (gpac_mux, "Creating new pad for serial %d", serial);
1.288 + printf ("XXXX new pad from template\n");
1.289 + newpad = gst_pad_new_from_template (templ, padname);
1.290 + g_free (padname);
1.291 +
1.292 + /* construct our own wrapper data structure for the pad to
1.293 + * keep track of its status */
1.294 + {
1.295 + GstGpacPad *gpacpad;
1.296 +
1.297 + gpacpad = (GstGpacPad *)
1.298 + gst_collect_pads_add_pad_full (gpac_mux->collect, newpad,
1.299 + sizeof (GstGpacPad), gst_gpac_mux_gpac_pad_destroy_notify);
1.300 +
1.301 + /* gpac new track */
1.302 + gpacpad->is_video = is_video;
1.303 + if (gpacpad->is_video) {
1.304 + gpacpad->track_number = gf_isom_new_track(gpac_mux->file, 0,
1.305 + GF_ISOM_MEDIA_VISUAL, 10 * 1000 /* time scale */);
1.306 + } else {
1.307 + gpacpad->track_number = gf_isom_new_track(gpac_mux->file, 0,
1.308 + GF_ISOM_MEDIA_AUDIO, 48000 /*time scale */);
1.309 +
1.310 + }
1.311 + if (gpacpad->track_number == 0) {
1.312 + g_warning ("Error while adding the new gpac track");
1.313 + } else {
1.314 + gf_isom_set_track_enabled(gpac_mux->file, gpacpad->track_number, 1);
1.315 + if (is_video) {
1.316 + GF_ESD *esd = gf_odf_desc_esd_new (0);
1.317 + esd->ESID = gf_isom_get_track_id(gpac_mux->file, gpacpad->track_number);
1.318 +
1.319 + gf_isom_new_mpeg4_description( gpac_mux->file, gpacpad->track_number,
1.320 + esd, NULL, NULL, &(gpacpad->di));
1.321 +
1.322 + gf_isom_set_visual_info (gpac_mux->file, gpacpad->track_number, gpacpad->di, 320, 240);//fixme
1.323 + //gf_isom_set_cts_packing (gpac_mux->file, gpacpad->track_number, 0);
1.324 + } else {
1.325 + GF_ESD *esd = gf_odf_desc_esd_new (2);
1.326 + esd->ESID = gf_isom_get_track_id(gpac_mux->file, gpacpad->track_number);
1.327 +
1.328 + gf_isom_new_mpeg4_description(gpac_mux->file, gpacpad->track_number,
1.329 + esd, NULL, NULL, &(gpacpad->di));
1.330 +
1.331 + gf_isom_set_audio_info(gpac_mux->file, gpacpad->track_number,
1.332 + gpacpad->di, 48000, 2 /*num channels */, 16);
1.333 + }
1.334 + }
1.335 + }
1.336 + }
1.337 +
1.338 + /* setup some pad functions */
1.339 + gst_pad_set_link_function (newpad, gst_gpac_mux_sinkconnect);
1.340 + /* dd the pad to the element */
1.341 + gst_element_add_pad (element, newpad);
1.342 +
1.343 + return newpad;
1.344 +
1.345 + /* ERRORS */
1.346 +wrong_direction:
1.347 + {
1.348 + g_warning ("gpac_mux: request pad that is not a SINK pad\n");
1.349 + return NULL;
1.350 + }
1.351 +wrong_template:
1.352 + {
1.353 + g_warning ("gpac_mux: this is not our template!\n");
1.354 + return NULL;
1.355 + }
1.356 +}
1.357 +
1.358 +static void
1.359 +gst_gpac_mux_release_pad (GstElement * element, GstPad * pad)
1.360 +{
1.361 + GstGpacMux *gpac_mux;
1.362 +
1.363 + gpac_mux = GST_GPAC_MUX (gst_pad_get_parent (pad));
1.364 +
1.365 + gst_collect_pads_remove_pad (gpac_mux->collect, pad);
1.366 + gst_element_remove_pad (element, pad);
1.367 +}
1.368 +
1.369 +/* handle events */
1.370 +static gboolean
1.371 +gst_gpac_mux_handle_src_event (GstPad * pad, GstEvent * event)
1.372 +{
1.373 + GstEventType type;
1.374 +
1.375 + type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
1.376 +
1.377 + switch (type) {
1.378 + case GST_EVENT_SEEK:
1.379 + /* disable seeking for now */
1.380 + return FALSE;
1.381 + default:
1.382 + break;
1.383 + }
1.384 +
1.385 + return gst_pad_event_default (pad, event);
1.386 +}
1.387 +
1.388 +static GstFlowReturn
1.389 +gst_gpac_mux_push_buffer (GstGpacMux * mux, GstBuffer * buffer)
1.390 +{
1.391 + GstCaps *caps;
1.392 +#if 0
1.393 + /* fix up OFFSET and OFFSET_END again */
1.394 + GST_BUFFER_OFFSET (buffer) = mux->offset;
1.395 + mux->offset += GST_BUFFER_SIZE (buffer);
1.396 + GST_BUFFER_OFFSET_END (buffer) = mux->offset;
1.397 +
1.398 + /* Ensure we have monotonically increasing timestamps in the output. */
1.399 + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
1.400 + if (mux->last_ts != GST_CLOCK_TIME_NONE &&
1.401 + GST_BUFFER_TIMESTAMP (buffer) < mux->last_ts)
1.402 + GST_BUFFER_TIMESTAMP (buffer) = mux->last_ts;
1.403 + else
1.404 + mux->last_ts = GST_BUFFER_TIMESTAMP (buffer);
1.405 + }
1.406 +#endif
1.407 +
1.408 + caps = gst_pad_get_negotiated_caps (mux->srcpad);
1.409 + gst_buffer_set_caps (buffer, caps);
1.410 + if (caps != NULL) {
1.411 + gst_caps_unref (caps);
1.412 + }
1.413 +
1.414 + return gst_pad_push (mux->srcpad, buffer);
1.415 +}
1.416 +
1.417 +static gboolean
1.418 +all_pads_eos (GstCollectPads * pads)
1.419 +{
1.420 + GSList *iter;
1.421 + gboolean alleos = TRUE;
1.422 +
1.423 + iter = pads->data;
1.424 + while (iter) {
1.425 + GstBuffer *buf;
1.426 + GstCollectData *data = (GstCollectData *) iter->data;
1.427 +
1.428 + buf = gst_collect_pads_peek (pads, data);
1.429 + if (buf) {
1.430 + alleos = FALSE;
1.431 + gst_buffer_unref (buf);
1.432 + goto beach;
1.433 + }
1.434 + iter = iter->next;
1.435 + }
1.436 +beach:
1.437 + return alleos;
1.438 +}
1.439 +
1.440 +static GstFlowReturn
1.441 +gst_gpac_mux_collected (GstCollectPads * pads, GstGpacMux * gpac_mux)
1.442 +{
1.443 + GstFlowReturn ret = GST_FLOW_OK;
1.444 + GSList *iter;
1.445 + GstBuffer *buf;
1.446 + gint i = 0;
1.447 +
1.448 + GST_LOG_OBJECT (gpac_mux, "collected");
1.449 +
1.450 + iter = gpac_mux->collect->data;
1.451 + while (iter) {
1.452 + GstCollectData *data = (GstCollectData *) iter->data;
1.453 + GstGpacPad *pad = (GstGpacPad *) data;
1.454 +
1.455 + buf = gst_collect_pads_pop (gpac_mux->collect, data);
1.456 + if (buf == NULL) {
1.457 + iter = g_slist_next (iter);
1.458 + continue;
1.459 + }
1.460 + GST_LOG_OBJECT (data->pad, "popped buffer %" GST_PTR_FORMAT, buf);
1.461 +
1.462 + /* gpac output */
1.463 + printf ("xxxxxx buffer size: %d\n", GST_BUFFER_SIZE(buf)); fflush (stdout);
1.464 + if (pad->frame_count < 300) {
1.465 + GF_ISOSample *sample = gf_isom_sample_new();
1.466 +
1.467 + sample->dataLength = GST_BUFFER_SIZE(buf);
1.468 + sample->data = GST_BUFFER_DATA(buf);
1.469 + sample->CTS_Offset = 0;
1.470 +
1.471 + if (pad->is_video) {
1.472 + sample->IsRAP = 0;
1.473 + sample->DTS += 1000*pad->frame_count;
1.474 + } else {
1.475 + sample->IsRAP = 0;
1.476 + sample->DTS = 2048*pad->frame_count;
1.477 + }
1.478 +
1.479 + gf_isom_add_sample(gpac_mux->file, pad->track_number,
1.480 + pad->di, sample);
1.481 + sample->data = NULL;
1.482 +
1.483 + gf_isom_sample_del(&sample);
1.484 +
1.485 + printf ("xxxx frames %d\n", pad->frame_count);
1.486 +
1.487 + } else if (pad->frame_count == 300) {
1.488 + printf ("XXX closing gpac output file\n"); fflush (stdout);
1.489 + gf_isom_close (gpac_mux->file);
1.490 + }
1.491 +
1.492 + /* gstreamer output (push) */
1.493 + if (gst_gpac_mux_push_buffer (gpac_mux, buf) != GST_FLOW_OK) {
1.494 + printf ("EEEEEEEE push failed\n");
1.495 + }
1.496 +
1.497 + iter = g_slist_next (iter);
1.498 + pad->frame_count++;
1.499 + i++;
1.500 + }
1.501 +
1.502 + /* fixme */
1.503 + return ret;
1.504 +}
1.505 +
1.506 +/* reset all variables in the gpac pads. */
1.507 +static void
1.508 +gst_gpac_mux_init_collectpads (GstCollectPads * collect)
1.509 +{
1.510 + GSList *walk;
1.511 +
1.512 + walk = collect->data;
1.513 + while (walk) {
1.514 + GstGpacPad *gpacpad = (GstGpacPad *) walk->data;
1.515 +
1.516 + //ogg_stream_init (&gpacpad->stream, gpacpad->serial);
1.517 + //gpacpad->packetno = 0;
1.518 + //gpacpad->pageno = 0;
1.519 + //gpacpad->eos = FALSE;
1.520 + /* we assume there will be some control data first for this pad */
1.521 + //gpacpad->state = GST_GPAC_PAD_STATE_CONTROL;
1.522 + //gpacpad->new_page = TRUE;
1.523 + //gpacpad->first_delta = FALSE;
1.524 + //gpacpad->prev_delta = FALSE;
1.525 + //gpacpad->pagebuffers = g_queue_new ();
1.526 +
1.527 + walk = g_slist_next (walk);
1.528 + }
1.529 +}
1.530 +
1.531 +/* Clear all buffers from the collectpads object */
1.532 +static void
1.533 +gst_gpac_mux_clear_collectpads (GstCollectPads * collect)
1.534 +{
1.535 + GSList *walk;
1.536 +
1.537 + for (walk = collect->data; walk; walk = g_slist_next (walk)) {
1.538 + GstGpacPad *gpacpad = (GstGpacPad *) walk->data;
1.539 + GstBuffer *buf;
1.540 +
1.541 + //gpac_stream_clear (&gpacpad->stream);
1.542 +/*
1.543 + while ((buf = g_queue_pop_head (gpacpad->pagebuffers)) != NULL) {
1.544 + gst_buffer_unref (buf);
1.545 + }
1.546 + g_queue_free (gpacpad->pagebuffers);
1.547 + gpacpad->pagebuffers = NULL;*/
1.548 + }
1.549 +}
1.550 +
1.551 +static GstStateChangeReturn
1.552 +gst_gpac_mux_change_state (GstElement * element, GstStateChange transition)
1.553 +{
1.554 + GstGpacMux *gpac_mux;
1.555 + GstStateChangeReturn ret;
1.556 +
1.557 + gpac_mux = GST_GPAC_MUX (element);
1.558 +
1.559 + switch (transition) {
1.560 + case GST_STATE_CHANGE_NULL_TO_READY:
1.561 + break;
1.562 + case GST_STATE_CHANGE_READY_TO_PAUSED:
1.563 + //gst_gpac_mux_clear (gpac_mux);
1.564 + //gst_gpac_mux_init_collectpads (gpac_mux->collect);
1.565 + gst_collect_pads_start (gpac_mux->collect);
1.566 + break;
1.567 + case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1.568 + break;
1.569 + case GST_STATE_CHANGE_PAUSED_TO_READY:
1.570 + gst_collect_pads_stop (gpac_mux->collect);
1.571 + break;
1.572 + default:
1.573 + break;
1.574 + }
1.575 +
1.576 + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1.577 +
1.578 + switch (transition) {
1.579 + case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1.580 + break;
1.581 + case GST_STATE_CHANGE_PAUSED_TO_READY:
1.582 + gst_gpac_mux_clear_collectpads (gpac_mux->collect);
1.583 + break;
1.584 + case GST_STATE_CHANGE_READY_TO_NULL:
1.585 + break;
1.586 + default:
1.587 + break;
1.588 + }
1.589 +
1.590 + return ret;
1.591 +
1.592 +}
1.593 +
1.594 +static gboolean
1.595 +gst_gpac_mux_plugin_init (GstPlugin * plugin)
1.596 +{
1.597 + return gst_element_register (plugin, "gpacmux", GST_RANK_NONE,
1.598 + GST_TYPE_GPAC_MUX);
1.599 +}
1.600 +
1.601 +GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
1.602 + GST_VERSION_MINOR,
1.603 + "gpacmux",
1.604 + "Muxes audio and video",
1.605 + gst_gpac_mux_plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
1.606 + GST_PACKAGE_ORIGIN)
1.607 +