Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gst-plugins-good.git] / gst / matroska / matroska-mux.c
1 /* GStreamer Matroska muxer/demuxer
2  * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  * (c) 2005 Michal Benes <michal.benes@xeris.cz>
4  * (c) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
5  *
6  * matroska-mux.c: matroska file/stream muxer
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /* TODO: - check everywhere that we don't write invalid values
25  *       - make sure timestamps are correctly scaled everywhere
26  */
27
28 /**
29  * SECTION:element-matroskamux
30  *
31  * matroskamux muxes different input streams into a Matroska file.
32  *
33  * <refsect2>
34  * <title>Example launch line</title>
35  * |[
36  * gst-launch -v filesrc location=/path/to/mp3 ! mp3parse ! matroskamux name=mux ! filesink location=test.mkv  filesrc location=/path/to/theora.ogg ! oggdemux ! theoraparse ! mux.
37  * ]| This pipeline muxes an MP3 file and a Ogg Theora video into a Matroska file.
38  * |[
39  * gst-launch -v audiotestsrc num-buffers=100 ! audioconvert ! vorbisenc ! matroskamux ! filesink location=test.mka
40  * ]| This pipeline muxes a 440Hz sine wave encoded with the Vorbis codec into a Matroska file.
41  * </refsect2>
42  */
43
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47
48 #include <math.h>
49 #include <stdio.h>
50 #include <string.h>
51
52 #include <gst/audio/audio.h>
53 #include <gst/riff/riff-media.h>
54 #include <gst/tag/tag.h>
55
56 #include "matroska-mux.h"
57 #include "matroska-ids.h"
58
59 GST_DEBUG_CATEGORY_STATIC (matroskamux_debug);
60 #define GST_CAT_DEFAULT matroskamux_debug
61
62 enum
63 {
64   ARG_0,
65   ARG_WRITING_APP,
66   ARG_DOCTYPE_VERSION,
67   ARG_MIN_INDEX_INTERVAL,
68   ARG_STREAMABLE
69 };
70
71 #define  DEFAULT_DOCTYPE_VERSION         2
72 #define  DEFAULT_WRITING_APP             "GStreamer Matroska muxer"
73 #define  DEFAULT_MIN_INDEX_INTERVAL      0
74 #define  DEFAULT_STREAMABLE              FALSE
75
76 /* WAVEFORMATEX is gst_riff_strf_auds + an extra guint16 extension size */
77 #define WAVEFORMATEX_SIZE  (2 + sizeof (gst_riff_strf_auds))
78
79 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
80     GST_PAD_SRC,
81     GST_PAD_ALWAYS,
82     GST_STATIC_CAPS ("video/x-matroska")
83     );
84
85 #define COMMON_VIDEO_CAPS \
86   "width = (int) [ 16, 4096 ], " \
87   "height = (int) [ 16, 4096 ], " \
88   "framerate = (fraction) [ 0, MAX ]"
89
90 #define COMMON_VIDEO_CAPS_NO_FRAMERATE \
91   "width = (int) [ 16, 4096 ], " \
92   "height = (int) [ 16, 4096 ] "
93
94 /* FIXME:
95  * * require codec data, etc as needed
96  */
97
98 static GstStaticPadTemplate videosink_templ =
99     GST_STATIC_PAD_TEMPLATE ("video_%u",
100     GST_PAD_SINK,
101     GST_PAD_REQUEST,
102     GST_STATIC_CAPS ("video/mpeg, "
103         "mpegversion = (int) { 1, 2, 4 }, "
104         "systemstream = (boolean) false, "
105         COMMON_VIDEO_CAPS "; "
106         "video/x-h264, stream-format=avc, alignment=au, "
107         COMMON_VIDEO_CAPS "; "
108         "video/x-divx, "
109         COMMON_VIDEO_CAPS "; "
110         "video/x-xvid, "
111         COMMON_VIDEO_CAPS "; "
112         "video/x-huffyuv, "
113         COMMON_VIDEO_CAPS "; "
114         "video/x-dv, "
115         COMMON_VIDEO_CAPS "; "
116         "video/x-h263, "
117         COMMON_VIDEO_CAPS "; "
118         "video/x-msmpeg, "
119         COMMON_VIDEO_CAPS "; "
120         "image/jpeg, "
121         COMMON_VIDEO_CAPS_NO_FRAMERATE "; "
122         "video/x-theora; "
123         "video/x-dirac, "
124         COMMON_VIDEO_CAPS "; "
125         "video/x-pn-realvideo, "
126         "rmversion = (int) [1, 4], "
127         COMMON_VIDEO_CAPS "; "
128         "video/x-vp8, "
129         COMMON_VIDEO_CAPS "; "
130         "video/x-raw, "
131         "format = (string) { YUY2, I420, YV12, UYVY, AYUV }, "
132         COMMON_VIDEO_CAPS "; "
133         "video/x-wmv, " "wmvversion = (int) [ 1, 3 ], " COMMON_VIDEO_CAPS)
134     );
135
136 #define COMMON_AUDIO_CAPS \
137   "channels = (int) [ 1, MAX ], " \
138   "rate = (int) [ 1, MAX ]"
139
140 /* FIXME:
141  * * require codec data, etc as needed
142  */
143 static GstStaticPadTemplate audiosink_templ =
144     GST_STATIC_PAD_TEMPLATE ("audio_%u",
145     GST_PAD_SINK,
146     GST_PAD_REQUEST,
147     GST_STATIC_CAPS ("audio/mpeg, "
148         "mpegversion = (int) 1, "
149         "layer = (int) [ 1, 3 ], "
150         "stream-format = (string) { raw }, "
151         COMMON_AUDIO_CAPS "; "
152         "audio/mpeg, "
153         "mpegversion = (int) { 2, 4 }, "
154         COMMON_AUDIO_CAPS "; "
155         "audio/x-ac3, "
156         COMMON_AUDIO_CAPS "; "
157         "audio/x-eac3, "
158         COMMON_AUDIO_CAPS "; "
159         "audio/x-dts, "
160         COMMON_AUDIO_CAPS "; "
161         "audio/x-vorbis, "
162         COMMON_AUDIO_CAPS "; "
163         "audio/x-flac, "
164         COMMON_AUDIO_CAPS "; "
165         "audio/x-speex, "
166         COMMON_AUDIO_CAPS "; "
167         "audio/x-raw, "
168         "format = (string) { U8, S16BE, S16LE, S24BE, S24LE, S32BE, S32LE, F32LE, F64LE }, "
169         COMMON_AUDIO_CAPS ";"
170         "audio/x-tta, "
171         "width = (int) { 8, 16, 24 }, "
172         "channels = (int) { 1, 2 }, " "rate = (int) [ 8000, 96000 ]; "
173         "audio/x-pn-realaudio, "
174         "raversion = (int) { 1, 2, 8 }, " COMMON_AUDIO_CAPS "; "
175         "audio/x-wma, " "wmaversion = (int) [ 1, 3 ], "
176         "block_align = (int) [ 0, 65535 ], bitrate = (int) [ 0, 524288 ], "
177         COMMON_AUDIO_CAPS ";"
178         "audio/x-alaw, "
179         "channels = (int) {1, 2}, " "rate = (int) [ 8000, 192000 ]; "
180         "audio/x-mulaw, "
181         "channels = (int) {1, 2}, " "rate = (int) [ 8000, 192000 ]")
182     );
183
184 static GstStaticPadTemplate subtitlesink_templ =
185 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
186     GST_PAD_SINK,
187     GST_PAD_REQUEST,
188     GST_STATIC_CAPS ("subtitle/x-kate"));
189
190 static GArray *used_uids;
191 G_LOCK_DEFINE_STATIC (used_uids);
192
193 #define parent_class gst_matroska_mux_parent_class
194 G_DEFINE_TYPE_WITH_CODE (GstMatroskaMux, gst_matroska_mux, GST_TYPE_ELEMENT,
195     G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
196
197 /* Matroska muxer destructor */
198 static void gst_matroska_mux_finalize (GObject * object);
199
200 /* Pads collected callback */
201 static GstFlowReturn
202 gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data);
203
204 /* pad functions */
205 static gboolean gst_matroska_mux_handle_src_event (GstPad * pad,
206     GstObject * parent, GstEvent * event);
207 static GstPad *gst_matroska_mux_request_new_pad (GstElement * element,
208     GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
209 static void gst_matroska_mux_release_pad (GstElement * element, GstPad * pad);
210
211 /* gst internal change state handler */
212 static GstStateChangeReturn
213 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition);
214
215 /* gobject bla bla */
216 static void gst_matroska_mux_set_property (GObject * object,
217     guint prop_id, const GValue * value, GParamSpec * pspec);
218 static void gst_matroska_mux_get_property (GObject * object,
219     guint prop_id, GValue * value, GParamSpec * pspec);
220
221 /* reset muxer */
222 static void gst_matroska_mux_reset (GstElement * element);
223
224 /* uid generation */
225 static guint64 gst_matroska_mux_create_uid ();
226
227 static gboolean theora_streamheader_to_codecdata (const GValue * streamheader,
228     GstMatroskaTrackContext * context);
229 static gboolean vorbis_streamheader_to_codecdata (const GValue * streamheader,
230     GstMatroskaTrackContext * context);
231 static gboolean speex_streamheader_to_codecdata (const GValue * streamheader,
232     GstMatroskaTrackContext * context);
233 static gboolean kate_streamheader_to_codecdata (const GValue * streamheader,
234     GstMatroskaTrackContext * context);
235 static gboolean flac_streamheader_to_codecdata (const GValue * streamheader,
236     GstMatroskaTrackContext * context);
237 static void
238 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
239     gpointer data);
240
241 static void
242 gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
243 {
244   GObjectClass *gobject_class;
245   GstElementClass *gstelement_class;
246
247   gobject_class = (GObjectClass *) klass;
248   gstelement_class = (GstElementClass *) klass;
249
250   gst_element_class_add_pad_template (gstelement_class,
251       gst_static_pad_template_get (&videosink_templ));
252   gst_element_class_add_pad_template (gstelement_class,
253       gst_static_pad_template_get (&audiosink_templ));
254   gst_element_class_add_pad_template (gstelement_class,
255       gst_static_pad_template_get (&subtitlesink_templ));
256   gst_element_class_add_pad_template (gstelement_class,
257       gst_static_pad_template_get (&src_templ));
258   gst_element_class_set_details_simple (gstelement_class, "Matroska muxer",
259       "Codec/Muxer",
260       "Muxes video/audio/subtitle streams into a matroska stream",
261       "GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
262
263   GST_DEBUG_CATEGORY_INIT (matroskamux_debug, "matroskamux", 0,
264       "Matroska muxer");
265
266   gobject_class->finalize = gst_matroska_mux_finalize;
267
268   gobject_class->get_property = gst_matroska_mux_get_property;
269   gobject_class->set_property = gst_matroska_mux_set_property;
270
271   g_object_class_install_property (gobject_class, ARG_WRITING_APP,
272       g_param_spec_string ("writing-app", "Writing application.",
273           "The name the application that creates the matroska file.",
274           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
275   g_object_class_install_property (gobject_class, ARG_DOCTYPE_VERSION,
276       g_param_spec_int ("version", "DocType version",
277           "This parameter determines what Matroska features can be used.",
278           1, 2, DEFAULT_DOCTYPE_VERSION,
279           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
280   g_object_class_install_property (gobject_class, ARG_MIN_INDEX_INTERVAL,
281       g_param_spec_int64 ("min-index-interval", "Minimum time between index "
282           "entries", "An index entry is created every so many nanoseconds.",
283           0, G_MAXINT64, DEFAULT_MIN_INDEX_INTERVAL,
284           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
285   g_object_class_install_property (gobject_class, ARG_STREAMABLE,
286       g_param_spec_boolean ("streamable", "Determines whether output should "
287           "be streamable", "If set to true, the output should be as if it is "
288           "to be streamed and hence no indexes written or duration written.",
289           DEFAULT_STREAMABLE,
290           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_STATIC_STRINGS));
291
292   gstelement_class->change_state =
293       GST_DEBUG_FUNCPTR (gst_matroska_mux_change_state);
294   gstelement_class->request_new_pad =
295       GST_DEBUG_FUNCPTR (gst_matroska_mux_request_new_pad);
296   gstelement_class->release_pad =
297       GST_DEBUG_FUNCPTR (gst_matroska_mux_release_pad);
298 }
299
300 /**
301  * Start of pad option handler code
302  */
303 #define DEFAULT_PAD_FRAME_DURATION TRUE
304 #define DEFAULT_PAD_FRAME_DURATION_VP8 FALSE
305
306 enum
307 {
308   PROP_PAD_0,
309   PROP_PAD_FRAME_DURATION
310 };
311
312 typedef struct
313 {
314   GstPad parent;
315   gboolean frame_duration;
316   gboolean frame_duration_user;
317 } GstMatroskamuxPad;
318
319 static void gst_matroskamux_pad_class_init (GstPadClass * klass);
320
321 static GType
322 gst_matroskamux_pad_get_type (void)
323 {
324   static GType type = 0;
325
326   if (G_UNLIKELY (type == 0)) {
327     type = g_type_register_static_simple (GST_TYPE_PAD,
328         g_intern_static_string ("GstMatroskamuxPad"), sizeof (GstPadClass),
329         (GClassInitFunc) gst_matroskamux_pad_class_init,
330         sizeof (GstMatroskamuxPad), NULL, 0);
331   }
332   return type;
333 }
334
335 #define GST_TYPE_MATROSKAMUX_PAD (gst_matroskamux_pad_get_type())
336 #define GST_MATROSKAMUX_PAD(pad) (G_TYPE_CHECK_INSTANCE_CAST((pad),GST_TYPE_MATROSKAMUX_PAD,GstMatroskamuxPad))
337 #define GST_MATROSKAMUX_PAD_CAST(pad) ((GstMatroskamuxPad *) pad)
338 #define GST_IS_MATROSKAMUX_PAD(pad) (G_TYPE_CHECK_INSTANCE_TYPE((pad),GST_TYPE_MATROSKAMUX_PAD))
339
340 static void
341 gst_matroskamux_pad_get_property (GObject * object, guint prop_id,
342     GValue * value, GParamSpec * pspec)
343 {
344   GstMatroskamuxPad *pad = GST_MATROSKAMUX_PAD (object);
345
346   switch (prop_id) {
347     case PROP_PAD_FRAME_DURATION:
348       g_value_set_boolean (value, pad->frame_duration);
349       break;
350     default:
351       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
352       break;
353   }
354 }
355
356 static void
357 gst_matroskamux_pad_set_property (GObject * object, guint prop_id,
358     const GValue * value, GParamSpec * pspec)
359 {
360   GstMatroskamuxPad *pad = GST_MATROSKAMUX_PAD (object);
361
362   switch (prop_id) {
363     case PROP_PAD_FRAME_DURATION:
364       pad->frame_duration = g_value_get_boolean (value);
365       pad->frame_duration_user = TRUE;
366       break;
367     default:
368       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
369       break;
370   }
371 }
372
373 static void
374 gst_matroskamux_pad_class_init (GstPadClass * klass)
375 {
376   GObjectClass *gobject_class = (GObjectClass *) klass;
377
378   gobject_class->set_property = gst_matroskamux_pad_set_property;
379   gobject_class->get_property = gst_matroskamux_pad_get_property;
380
381   g_object_class_install_property (gobject_class, PROP_PAD_FRAME_DURATION,
382       g_param_spec_boolean ("frame-duration", "Frame duration",
383           "Default frame duration", DEFAULT_PAD_FRAME_DURATION,
384           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
385 }
386
387 static void
388 gst_matroskamux_pad_init (GstMatroskamuxPad * pad)
389 {
390   pad->frame_duration = DEFAULT_PAD_FRAME_DURATION;
391   pad->frame_duration_user = FALSE;
392 }
393
394 /*
395  * End of pad option handler code
396  **/
397
398 /**
399  * gst_matroska_mux_init:
400  * @mux: #GstMatroskaMux that should be initialized.
401  * @g_class: Class of the muxer.
402  *
403  * Matroska muxer constructor.
404  */
405 static void
406 gst_matroska_mux_init (GstMatroskaMux * mux)
407 {
408   GstPadTemplate *templ;
409
410   templ =
411       gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (mux), "src");
412   mux->srcpad = gst_pad_new_from_template (templ, "src");
413
414   gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event);
415   gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
416
417   mux->collect = gst_collect_pads_new ();
418   gst_collect_pads_set_function (mux->collect,
419       (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_matroska_mux_collected),
420       mux);
421
422   mux->ebml_write = gst_ebml_write_new (mux->srcpad);
423   mux->doctype = GST_MATROSKA_DOCTYPE_MATROSKA;
424
425   /* property defaults */
426   mux->doctype_version = DEFAULT_DOCTYPE_VERSION;
427   mux->writing_app = g_strdup (DEFAULT_WRITING_APP);
428   mux->min_index_interval = DEFAULT_MIN_INDEX_INTERVAL;
429   mux->streamable = DEFAULT_STREAMABLE;
430
431   /* initialize internal variables */
432   mux->index = NULL;
433   mux->num_streams = 0;
434   mux->num_a_streams = 0;
435   mux->num_t_streams = 0;
436   mux->num_v_streams = 0;
437
438   /* initialize remaining variables */
439   gst_matroska_mux_reset (GST_ELEMENT (mux));
440 }
441
442
443 /**
444  * gst_matroska_mux_finalize:
445  * @object: #GstMatroskaMux that should be finalized.
446  *
447  * Finalize matroska muxer.
448  */
449 static void
450 gst_matroska_mux_finalize (GObject * object)
451 {
452   GstMatroskaMux *mux = GST_MATROSKA_MUX (object);
453
454   gst_event_replace (&mux->force_key_unit_event, NULL);
455
456   gst_object_unref (mux->collect);
457   gst_object_unref (mux->ebml_write);
458   if (mux->writing_app)
459     g_free (mux->writing_app);
460
461   G_OBJECT_CLASS (parent_class)->finalize (object);
462 }
463
464
465 /**
466  * gst_matroska_mux_create_uid:
467  *
468  * Generate new unused track UID.
469  *
470  * Returns: New track UID.
471  */
472 static guint64
473 gst_matroska_mux_create_uid (void)
474 {
475   guint64 uid = 0;
476
477   G_LOCK (used_uids);
478
479   if (!used_uids)
480     used_uids = g_array_sized_new (FALSE, FALSE, sizeof (guint64), 10);
481
482   while (!uid) {
483     guint i;
484
485     uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
486     for (i = 0; i < used_uids->len; i++) {
487       if (g_array_index (used_uids, guint64, i) == uid) {
488         uid = 0;
489         break;
490       }
491     }
492     g_array_append_val (used_uids, uid);
493   }
494
495   G_UNLOCK (used_uids);
496   return uid;
497 }
498
499
500 /**
501  * gst_matroska_pad_reset:
502  * @collect_pad: the #GstMatroskaPad
503  *
504  * Reset and/or release resources of a matroska collect pad.
505  */
506 static void
507 gst_matroska_pad_reset (GstMatroskaPad * collect_pad, gboolean full)
508 {
509   gchar *name = NULL;
510   GstMatroskaTrackType type = 0;
511
512   /* free track information */
513   if (collect_pad->track != NULL) {
514     /* retrieve for optional later use */
515     name = collect_pad->track->name;
516     type = collect_pad->track->type;
517     /* extra for video */
518     if (type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
519       GstMatroskaTrackVideoContext *ctx =
520           (GstMatroskaTrackVideoContext *) collect_pad->track;
521
522       if (ctx->dirac_unit) {
523         gst_buffer_unref (ctx->dirac_unit);
524         ctx->dirac_unit = NULL;
525       }
526     }
527     g_free (collect_pad->track->codec_id);
528     g_free (collect_pad->track->codec_name);
529     if (full)
530       g_free (collect_pad->track->name);
531     g_free (collect_pad->track->language);
532     g_free (collect_pad->track->codec_priv);
533     g_free (collect_pad->track);
534     collect_pad->track = NULL;
535   }
536
537   /* free cached buffer */
538   if (collect_pad->buffer != NULL) {
539     gst_buffer_unref (collect_pad->buffer);
540     collect_pad->buffer = NULL;
541   }
542
543   if (!full && type != 0) {
544     GstMatroskaTrackContext *context;
545
546     /* create a fresh context */
547     switch (type) {
548       case GST_MATROSKA_TRACK_TYPE_VIDEO:
549         context = (GstMatroskaTrackContext *)
550             g_new0 (GstMatroskaTrackVideoContext, 1);
551         break;
552       case GST_MATROSKA_TRACK_TYPE_AUDIO:
553         context = (GstMatroskaTrackContext *)
554             g_new0 (GstMatroskaTrackAudioContext, 1);
555         break;
556       case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
557         context = (GstMatroskaTrackContext *)
558             g_new0 (GstMatroskaTrackSubtitleContext, 1);
559         break;
560       default:
561         g_assert_not_reached ();
562         return;
563     }
564
565     context->type = type;
566     context->name = name;
567     /* TODO: check default values for the context */
568     context->flags = GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT;
569     collect_pad->track = context;
570     collect_pad->buffer = NULL;
571     collect_pad->duration = 0;
572     collect_pad->start_ts = GST_CLOCK_TIME_NONE;
573     collect_pad->end_ts = GST_CLOCK_TIME_NONE;
574   }
575 }
576
577 /**
578  * gst_matroska_pad_free:
579  * @collect_pad: the #GstMatroskaPad
580  *
581  * Release resources of a matroska collect pad.
582  */
583 static void
584 gst_matroska_pad_free (GstPad * collect_pad)
585 {
586   gst_matroska_pad_reset ((GstMatroskaPad *) collect_pad, TRUE);
587 }
588
589
590 /**
591  * gst_matroska_mux_reset:
592  * @element: #GstMatroskaMux that should be reseted.
593  *
594  * Reset matroska muxer back to initial state.
595  */
596 static void
597 gst_matroska_mux_reset (GstElement * element)
598 {
599   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
600   GSList *walk;
601
602   /* reset EBML write */
603   gst_ebml_write_reset (mux->ebml_write);
604
605   /* reset input */
606   mux->state = GST_MATROSKA_MUX_STATE_START;
607
608   /* clean up existing streams */
609
610   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
611     GstMatroskaPad *collect_pad;
612
613     collect_pad = (GstMatroskaPad *) walk->data;
614
615     /* reset collect pad to pristine state */
616     gst_matroska_pad_reset (collect_pad, FALSE);
617   }
618
619   /* reset indexes */
620   mux->num_indexes = 0;
621   g_free (mux->index);
622   mux->index = NULL;
623
624   /* reset timers */
625   mux->time_scale = GST_MSECOND;
626   mux->max_cluster_duration = G_MAXINT16 * mux->time_scale;
627   mux->duration = 0;
628
629   /* reset cluster */
630   mux->cluster = 0;
631   mux->cluster_time = 0;
632   mux->cluster_pos = 0;
633   mux->prev_cluster_size = 0;
634
635   /* reset tags */
636   gst_tag_setter_reset_tags (GST_TAG_SETTER (mux));
637 }
638
639 /**
640  * gst_matroska_mux_handle_src_event:
641  * @pad: Pad which received the event.
642  * @event: Received event.
643  *
644  * handle events - copied from oggmux without understanding
645  *
646  * Returns: #TRUE on success.
647  */
648 static gboolean
649 gst_matroska_mux_handle_src_event (GstPad * pad, GstObject * parent,
650     GstEvent * event)
651 {
652   GstEventType type;
653
654   type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
655
656   switch (type) {
657     case GST_EVENT_SEEK:
658       /* disable seeking for now */
659       return FALSE;
660     default:
661       break;
662   }
663
664   return gst_pad_event_default (pad, parent, event);
665 }
666
667 /**
668  * gst_matroska_mux_handle_sink_event:
669  * @pad: Pad which received the event.
670  * @event: Received event.
671  *
672  * handle events - informational ones like tags
673  *
674  * Returns: #TRUE on success.
675  */
676 static gboolean
677 gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
678     GstEvent * event)
679 {
680   GstMatroskaTrackContext *context;
681   GstMatroskaPad *collect_pad;
682   GstMatroskaMux *mux = GST_MATROSKA_MUX (parent);
683   GstTagList *list;
684   gboolean ret = TRUE;
685
686   switch (GST_EVENT_TYPE (event)) {
687     case GST_EVENT_CAPS:{
688       GstCaps *caps;
689
690       collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
691       gst_event_parse_caps (event, &caps);
692
693       ret = collect_pad->capsfunc (pad, caps);
694       gst_event_unref (event);
695       event = NULL;
696       break;
697     }
698     case GST_EVENT_TAG:{
699       gchar *lang = NULL;
700
701       GST_DEBUG_OBJECT (mux, "received tag event");
702       gst_event_parse_tag (event, &list);
703
704       collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
705       g_assert (collect_pad);
706       context = collect_pad->track;
707       g_assert (context);
708
709       /* Matroska wants ISO 639-2B code, taglist most likely contains 639-1 */
710       if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) {
711         const gchar *lang_code;
712
713         lang_code = gst_tag_get_language_code_iso_639_2B (lang);
714         if (lang_code) {
715           GST_INFO_OBJECT (pad, "Setting language to '%s'", lang_code);
716           context->language = g_strdup (lang_code);
717         } else {
718           GST_WARNING_OBJECT (pad, "Did not get language code for '%s'", lang);
719         }
720         g_free (lang);
721       }
722
723       /* FIXME: what about stream-specific tags? */
724       gst_tag_setter_merge_tags (GST_TAG_SETTER (mux), list,
725           gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (mux)));
726
727       gst_event_unref (event);
728       /* handled this, don't want collectpads to forward it downstream */
729       event = NULL;
730       break;
731     }
732     case GST_EVENT_SEGMENT:{
733       const GstSegment *segment;
734
735       gst_event_parse_segment (event, &segment);
736       if (segment->format != GST_FORMAT_TIME) {
737         ret = FALSE;
738         gst_event_unref (event);
739         event = NULL;
740       }
741       break;
742     }
743     case GST_EVENT_CUSTOM_DOWNSTREAM:{
744       const GstStructure *structure;
745
746       structure = gst_event_get_structure (event);
747       if (gst_structure_has_name (structure, "GstForceKeyUnit")) {
748         gst_event_replace (&mux->force_key_unit_event, NULL);
749         mux->force_key_unit_event = event;
750         event = NULL;
751       }
752       break;
753     }
754     default:
755       break;
756   }
757
758   /* now GstCollectPads can take care of the rest, e.g. EOS */
759   if (event)
760     ret = mux->collect_event (pad, parent, event);
761
762   return ret;
763 }
764
765
766 /**
767  * gst_matroska_mux_video_pad_setcaps:
768  * @pad: Pad which got the caps.
769  * @caps: New caps.
770  *
771  * Setcaps function for video sink pad.
772  *
773  * Returns: #TRUE on success.
774  */
775 static gboolean
776 gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
777 {
778   GstMatroskaTrackContext *context = NULL;
779   GstMatroskaTrackVideoContext *videocontext;
780   GstMatroskaMux *mux;
781   GstMatroskaPad *collect_pad;
782   GstStructure *structure;
783   const gchar *mimetype;
784   const GValue *value = NULL;
785   GstBuffer *codec_buf = NULL;
786   gint width, height, pixel_width, pixel_height;
787   gint fps_d, fps_n;
788   gboolean interlaced = FALSE;
789
790   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
791
792   /* find context */
793   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
794   g_assert (collect_pad);
795   context = collect_pad->track;
796   g_assert (context);
797   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO);
798   videocontext = (GstMatroskaTrackVideoContext *) context;
799
800   /* gst -> matroska ID'ing */
801   structure = gst_caps_get_structure (caps, 0);
802
803   mimetype = gst_structure_get_name (structure);
804
805   if (gst_structure_get_boolean (structure, "interlaced", &interlaced)
806       && interlaced)
807     context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
808
809   if (!strcmp (mimetype, "video/x-theora")) {
810     /* we'll extract the details later from the theora identification header */
811     goto skip_details;
812   }
813
814   /* get general properties */
815   /* spec says it is mandatory */
816   if (!gst_structure_get_int (structure, "width", &width) ||
817       !gst_structure_get_int (structure, "height", &height))
818     goto refuse_caps;
819
820   videocontext->pixel_width = width;
821   videocontext->pixel_height = height;
822
823   /* set vp8 defaults or let user override it */
824   if (GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration_user == FALSE
825       && (!strcmp (mimetype, "video/x-vp8")))
826     GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration =
827         DEFAULT_PAD_FRAME_DURATION_VP8;
828
829   if (GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration
830       && gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)
831       && fps_n > 0) {
832     context->default_duration =
833         gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
834     GST_LOG_OBJECT (pad, "default duration = %" GST_TIME_FORMAT,
835         GST_TIME_ARGS (context->default_duration));
836   } else {
837     context->default_duration = 0;
838   }
839   if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
840           &pixel_width, &pixel_height)) {
841     if (pixel_width > pixel_height) {
842       videocontext->display_width = width * pixel_width / pixel_height;
843       videocontext->display_height = height;
844     } else if (pixel_width < pixel_height) {
845       videocontext->display_width = width;
846       videocontext->display_height = height * pixel_height / pixel_width;
847     } else {
848       videocontext->display_width = 0;
849       videocontext->display_height = 0;
850     }
851   } else {
852     videocontext->display_width = 0;
853     videocontext->display_height = 0;
854   }
855
856 skip_details:
857
858   videocontext->asr_mode = GST_MATROSKA_ASPECT_RATIO_MODE_FREE;
859   videocontext->fourcc = 0;
860
861   /* TODO: - check if we handle all codecs by the spec, i.e. codec private
862    *         data and other settings
863    *       - add new formats
864    */
865
866   /* extract codec_data, may turn out needed */
867   value = gst_structure_get_value (structure, "codec_data");
868   if (value)
869     codec_buf = (GstBuffer *) gst_value_get_buffer (value);
870
871   /* find type */
872   if (!strcmp (mimetype, "video/x-raw")) {
873     const gchar *fstr;
874     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
875     fstr = gst_structure_get_string (structure, "format");
876     if (fstr && strlen (fstr) == 4)
877       videocontext->fourcc = GST_STR_FOURCC (fstr);
878   } else if (!strcmp (mimetype, "image/jpeg")) {
879     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
880   } else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
881       ||!strcmp (mimetype, "video/x-huffyuv")
882       || !strcmp (mimetype, "video/x-divx")
883       || !strcmp (mimetype, "video/x-dv")
884       || !strcmp (mimetype, "video/x-h263")
885       || !strcmp (mimetype, "video/x-msmpeg")
886       || !strcmp (mimetype, "video/x-wmv")
887       || !strcmp (mimetype, "image/jpeg")) {
888     gst_riff_strf_vids *bih;
889     gint size = sizeof (gst_riff_strf_vids);
890     guint32 fourcc = 0;
891
892     if (!strcmp (mimetype, "video/x-xvid"))
893       fourcc = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
894     else if (!strcmp (mimetype, "video/x-huffyuv"))
895       fourcc = GST_MAKE_FOURCC ('H', 'F', 'Y', 'U');
896     else if (!strcmp (mimetype, "video/x-dv"))
897       fourcc = GST_MAKE_FOURCC ('D', 'V', 'S', 'D');
898     else if (!strcmp (mimetype, "video/x-h263"))
899       fourcc = GST_MAKE_FOURCC ('H', '2', '6', '3');
900     else if (!strcmp (mimetype, "video/x-divx")) {
901       gint divxversion;
902
903       gst_structure_get_int (structure, "divxversion", &divxversion);
904       switch (divxversion) {
905         case 3:
906           fourcc = GST_MAKE_FOURCC ('D', 'I', 'V', '3');
907           break;
908         case 4:
909           fourcc = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
910           break;
911         case 5:
912           fourcc = GST_MAKE_FOURCC ('D', 'X', '5', '0');
913           break;
914       }
915     } else if (!strcmp (mimetype, "video/x-msmpeg")) {
916       gint msmpegversion;
917
918       gst_structure_get_int (structure, "msmpegversion", &msmpegversion);
919       switch (msmpegversion) {
920         case 41:
921           fourcc = GST_MAKE_FOURCC ('M', 'P', 'G', '4');
922           break;
923         case 42:
924           fourcc = GST_MAKE_FOURCC ('M', 'P', '4', '2');
925           break;
926         case 43:
927           goto msmpeg43;
928           break;
929       }
930     } else if (!strcmp (mimetype, "video/x-wmv")) {
931       gint wmvversion;
932       const gchar *fstr;
933
934       fstr = gst_structure_get_string (structure, "format");
935       if (fstr && strlen (fstr) == 4) {
936         fourcc = GST_STR_FOURCC (fstr);
937       } else if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) {
938         if (wmvversion == 2) {
939           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '2');
940         } else if (wmvversion == 1) {
941           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '1');
942         } else if (wmvversion == 3) {
943           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
944         }
945       }
946     } else if (!strcmp (mimetype, "image/jpeg")) {
947       fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
948     }
949
950     if (!fourcc)
951       goto refuse_caps;
952
953     bih = g_new0 (gst_riff_strf_vids, 1);
954     GST_WRITE_UINT32_LE (&bih->size, size);
955     GST_WRITE_UINT32_LE (&bih->width, videocontext->pixel_width);
956     GST_WRITE_UINT32_LE (&bih->height, videocontext->pixel_height);
957     GST_WRITE_UINT32_LE (&bih->compression, fourcc);
958     GST_WRITE_UINT16_LE (&bih->planes, (guint16) 1);
959     GST_WRITE_UINT16_LE (&bih->bit_cnt, (guint16) 24);
960     GST_WRITE_UINT32_LE (&bih->image_size, videocontext->pixel_width *
961         videocontext->pixel_height * 3);
962
963     /* process codec private/initialization data, if any */
964     if (codec_buf) {
965       size += gst_buffer_get_size (codec_buf);
966       bih = g_realloc (bih, size);
967       GST_WRITE_UINT32_LE (&bih->size, size);
968       gst_buffer_extract (codec_buf, 0,
969           (guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
970     }
971
972     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
973     context->codec_priv = (gpointer) bih;
974     context->codec_priv_size = size;
975   } else if (!strcmp (mimetype, "video/x-h264")) {
976     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC);
977
978     if (context->codec_priv != NULL) {
979       g_free (context->codec_priv);
980       context->codec_priv = NULL;
981       context->codec_priv_size = 0;
982     }
983
984     /* Create avcC header */
985     if (codec_buf != NULL) {
986       context->codec_priv_size = gst_buffer_get_size (codec_buf);
987       context->codec_priv = g_malloc0 (context->codec_priv_size);
988       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
989     }
990   } else if (!strcmp (mimetype, "video/x-theora")) {
991     const GValue *streamheader;
992
993     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_THEORA);
994
995     if (context->codec_priv != NULL) {
996       g_free (context->codec_priv);
997       context->codec_priv = NULL;
998       context->codec_priv_size = 0;
999     }
1000
1001     streamheader = gst_structure_get_value (structure, "streamheader");
1002     if (!theora_streamheader_to_codecdata (streamheader, context)) {
1003       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1004           ("theora stream headers missing or malformed"));
1005       goto refuse_caps;
1006     }
1007   } else if (!strcmp (mimetype, "video/x-dirac")) {
1008     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_DIRAC);
1009   } else if (!strcmp (mimetype, "video/x-vp8")) {
1010     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VP8);
1011   } else if (!strcmp (mimetype, "video/mpeg")) {
1012     gint mpegversion;
1013
1014     gst_structure_get_int (structure, "mpegversion", &mpegversion);
1015     switch (mpegversion) {
1016       case 1:
1017         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG1);
1018         break;
1019       case 2:
1020         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG2);
1021         break;
1022       case 4:
1023         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP);
1024         break;
1025       default:
1026         goto refuse_caps;
1027     }
1028
1029     /* global headers may be in codec data */
1030     if (codec_buf != NULL) {
1031       context->codec_priv_size = gst_buffer_get_size (codec_buf);
1032       context->codec_priv = g_malloc0 (context->codec_priv_size);
1033       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
1034     }
1035   } else if (!strcmp (mimetype, "video/x-msmpeg")) {
1036   msmpeg43:
1037     /* can only make it here if preceding case verified it was version 3 */
1038     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3);
1039   } else if (!strcmp (mimetype, "video/x-pn-realvideo")) {
1040     gint rmversion;
1041     const GValue *mdpr_data;
1042
1043     gst_structure_get_int (structure, "rmversion", &rmversion);
1044     switch (rmversion) {
1045       case 1:
1046         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
1047         break;
1048       case 2:
1049         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
1050         break;
1051       case 3:
1052         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
1053         break;
1054       case 4:
1055         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
1056         break;
1057       default:
1058         goto refuse_caps;
1059     }
1060
1061     mdpr_data = gst_structure_get_value (structure, "mdpr_data");
1062     if (mdpr_data != NULL) {
1063       guint8 *priv_data = NULL;
1064       guint priv_data_size = 0;
1065
1066       GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
1067
1068       priv_data_size = gst_buffer_get_size (codec_data_buf);
1069       priv_data = g_malloc0 (priv_data_size);
1070
1071       gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
1072
1073       context->codec_priv = priv_data;
1074       context->codec_priv_size = priv_data_size;
1075     }
1076   }
1077
1078   return TRUE;
1079
1080   /* ERRORS */
1081 refuse_caps:
1082   {
1083     GST_WARNING_OBJECT (mux, "pad %s refused caps %" GST_PTR_FORMAT,
1084         GST_PAD_NAME (pad), caps);
1085     return FALSE;
1086   }
1087 }
1088
1089 /* N > 0 to expect a particular number of headers, negative if the
1090    number of headers is variable */
1091 static gboolean
1092 xiphN_streamheader_to_codecdata (const GValue * streamheader,
1093     GstMatroskaTrackContext * context, GstBuffer ** p_buf0, int N)
1094 {
1095   GstBuffer **buf = NULL;
1096   GArray *bufarr;
1097   guint8 *priv_data;
1098   guint bufi, i, offset, priv_data_size;
1099
1100   if (streamheader == NULL)
1101     goto no_stream_headers;
1102
1103   if (G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY)
1104     goto wrong_type;
1105
1106   bufarr = g_value_peek_pointer (streamheader);
1107   if (bufarr->len <= 0 || bufarr->len > 255)    /* at least one header, and count stored in a byte */
1108     goto wrong_count;
1109   if (N > 0 && bufarr->len != N)
1110     goto wrong_count;
1111
1112   context->xiph_headers_to_skip = bufarr->len;
1113
1114   buf = (GstBuffer **) g_malloc0 (sizeof (GstBuffer *) * bufarr->len);
1115   for (i = 0; i < bufarr->len; i++) {
1116     GValue *bufval = &g_array_index (bufarr, GValue, i);
1117
1118     if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1119       g_free (buf);
1120       goto wrong_content_type;
1121     }
1122
1123     buf[i] = g_value_peek_pointer (bufval);
1124   }
1125
1126   priv_data_size = 1;
1127   if (bufarr->len > 0) {
1128     for (i = 0; i < bufarr->len - 1; i++) {
1129       priv_data_size += gst_buffer_get_size (buf[i]) / 0xff + 1;
1130     }
1131   }
1132
1133   for (i = 0; i < bufarr->len; ++i) {
1134     priv_data_size += gst_buffer_get_size (buf[i]);
1135   }
1136
1137   priv_data = g_malloc0 (priv_data_size);
1138
1139   priv_data[0] = bufarr->len - 1;
1140   offset = 1;
1141
1142   if (bufarr->len > 0) {
1143     for (bufi = 0; bufi < bufarr->len - 1; bufi++) {
1144       for (i = 0; i < gst_buffer_get_size (buf[bufi]) / 0xff; ++i) {
1145         priv_data[offset++] = 0xff;
1146       }
1147       priv_data[offset++] = gst_buffer_get_size (buf[bufi]) % 0xff;
1148     }
1149   }
1150
1151   for (i = 0; i < bufarr->len; ++i) {
1152     gst_buffer_extract (buf[i], 0, priv_data + offset, -1);
1153     offset += gst_buffer_get_size (buf[i]);
1154   }
1155
1156   context->codec_priv = priv_data;
1157   context->codec_priv_size = priv_data_size;
1158
1159   if (p_buf0)
1160     *p_buf0 = gst_buffer_ref (buf[0]);
1161
1162   g_free (buf);
1163
1164   return TRUE;
1165
1166 /* ERRORS */
1167 no_stream_headers:
1168   {
1169     GST_WARNING ("required streamheaders missing in sink caps!");
1170     return FALSE;
1171   }
1172 wrong_type:
1173   {
1174     GST_WARNING ("streamheaders are not a GST_TYPE_ARRAY, but a %s",
1175         G_VALUE_TYPE_NAME (streamheader));
1176     return FALSE;
1177   }
1178 wrong_count:
1179   {
1180     GST_WARNING ("got %u streamheaders, not %d as expected", bufarr->len, N);
1181     return FALSE;
1182   }
1183 wrong_content_type:
1184   {
1185     GST_WARNING ("streamheaders array does not contain GstBuffers");
1186     return FALSE;
1187   }
1188 }
1189
1190 static gboolean
1191 vorbis_streamheader_to_codecdata (const GValue * streamheader,
1192     GstMatroskaTrackContext * context)
1193 {
1194   GstBuffer *buf0 = NULL;
1195
1196   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
1197     return FALSE;
1198
1199   if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 4) {
1200     GST_WARNING ("First vorbis header too small, ignoring");
1201   } else {
1202     if (gst_buffer_memcmp (buf0, 1, "vorbis", 6) == 0) {
1203       GstMatroskaTrackAudioContext *audiocontext;
1204       guint8 *data, *hdr;
1205
1206       data = gst_buffer_map (buf0, NULL, NULL, GST_MAP_READ);
1207       hdr = data + 1 + 6 + 4;
1208       audiocontext = (GstMatroskaTrackAudioContext *) context;
1209       audiocontext->channels = GST_READ_UINT8 (hdr);
1210       audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1);
1211       gst_buffer_unmap (buf0, data, -1);
1212     }
1213   }
1214
1215   if (buf0)
1216     gst_buffer_unref (buf0);
1217
1218   return TRUE;
1219 }
1220
1221 static gboolean
1222 theora_streamheader_to_codecdata (const GValue * streamheader,
1223     GstMatroskaTrackContext * context)
1224 {
1225   GstBuffer *buf0 = NULL;
1226
1227   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
1228     return FALSE;
1229
1230   if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 26) {
1231     GST_WARNING ("First theora header too small, ignoring");
1232   } else if (gst_buffer_memcmp (buf0, 0, "\200theora\003\002", 9) != 0) {
1233     GST_WARNING ("First header not a theora identification header, ignoring");
1234   } else {
1235     GstMatroskaTrackVideoContext *videocontext;
1236     guint fps_num, fps_denom, par_num, par_denom;
1237     guint8 *data, *hdr;
1238
1239     data = gst_buffer_map (buf0, NULL, NULL, GST_MAP_READ);
1240     hdr = data + 1 + 6 + 3 + 2 + 2;
1241
1242     videocontext = (GstMatroskaTrackVideoContext *) context;
1243     videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8;
1244     videocontext->pixel_height = GST_READ_UINT32_BE (hdr + 3) >> 8;
1245     hdr += 3 + 3 + 1 + 1;
1246     fps_num = GST_READ_UINT32_BE (hdr);
1247     fps_denom = GST_READ_UINT32_BE (hdr + 4);
1248     context->default_duration = gst_util_uint64_scale_int (GST_SECOND,
1249         fps_denom, fps_num);
1250     hdr += 4 + 4;
1251     par_num = GST_READ_UINT32_BE (hdr) >> 8;
1252     par_denom = GST_READ_UINT32_BE (hdr + 3) >> 8;
1253     if (par_num > 0 && par_num > 0) {
1254       if (par_num > par_denom) {
1255         videocontext->display_width =
1256             videocontext->pixel_width * par_num / par_denom;
1257         videocontext->display_height = videocontext->pixel_height;
1258       } else if (par_num < par_denom) {
1259         videocontext->display_width = videocontext->pixel_width;
1260         videocontext->display_height =
1261             videocontext->pixel_height * par_denom / par_num;
1262       } else {
1263         videocontext->display_width = 0;
1264         videocontext->display_height = 0;
1265       }
1266     } else {
1267       videocontext->display_width = 0;
1268       videocontext->display_height = 0;
1269     }
1270     hdr += 3 + 3;
1271
1272     gst_buffer_unmap (buf0, data, -1);
1273   }
1274
1275   if (buf0)
1276     gst_buffer_unref (buf0);
1277
1278   return TRUE;
1279 }
1280
1281 static gboolean
1282 kate_streamheader_to_codecdata (const GValue * streamheader,
1283     GstMatroskaTrackContext * context)
1284 {
1285   GstBuffer *buf0 = NULL;
1286
1287   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1))
1288     return FALSE;
1289
1290   if (buf0 == NULL || gst_buffer_get_size (buf0) < 64) {        /* Kate ID header is 64 bytes */
1291     GST_WARNING ("First kate header too small, ignoring");
1292   } else if (gst_buffer_memcmp (buf0, 0, "\200kate\0\0\0", 8) != 0) {
1293     GST_WARNING ("First header not a kate identification header, ignoring");
1294   }
1295
1296   if (buf0)
1297     gst_buffer_unref (buf0);
1298
1299   return TRUE;
1300 }
1301
1302 static gboolean
1303 flac_streamheader_to_codecdata (const GValue * streamheader,
1304     GstMatroskaTrackContext * context)
1305 {
1306   GArray *bufarr;
1307   gint i;
1308   GValue *bufval;
1309   GstBuffer *buffer;
1310
1311   if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
1312     GST_WARNING ("No or invalid streamheader field in the caps");
1313     return FALSE;
1314   }
1315
1316   bufarr = g_value_peek_pointer (streamheader);
1317   if (bufarr->len < 2) {
1318     GST_WARNING ("Too few headers in streamheader field");
1319     return FALSE;
1320   }
1321
1322   context->xiph_headers_to_skip = bufarr->len + 1;
1323
1324   bufval = &g_array_index (bufarr, GValue, 0);
1325   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1326     GST_WARNING ("streamheaders array does not contain GstBuffers");
1327     return FALSE;
1328   }
1329
1330   buffer = g_value_peek_pointer (bufval);
1331
1332   /* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */
1333   if (gst_buffer_get_size (buffer) < 9 + 4 + 4 + 34
1334       || gst_buffer_memcmp (buffer, 1, "FLAC", 4) != 0
1335       || gst_buffer_memcmp (buffer, 9, "fLaC", 4) != 0) {
1336     GST_WARNING ("Invalid streamheader for FLAC");
1337     return FALSE;
1338   }
1339
1340   context->codec_priv_size = gst_buffer_get_size (buffer) - 9;
1341   context->codec_priv = g_malloc (context->codec_priv_size);
1342   gst_buffer_extract (buffer, 9, context->codec_priv, -1);
1343
1344   for (i = 1; i < bufarr->len; i++) {
1345     guint old_size;
1346     bufval = &g_array_index (bufarr, GValue, i);
1347
1348     if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1349       g_free (context->codec_priv);
1350       context->codec_priv = NULL;
1351       context->codec_priv_size = 0;
1352       GST_WARNING ("streamheaders array does not contain GstBuffers");
1353       return FALSE;
1354     }
1355
1356     buffer = g_value_peek_pointer (bufval);
1357
1358     old_size = context->codec_priv_size;
1359     context->codec_priv_size += gst_buffer_get_size (buffer);
1360
1361     context->codec_priv = g_realloc (context->codec_priv,
1362         context->codec_priv_size);
1363     gst_buffer_extract (buffer, 0,
1364         (guint8 *) context->codec_priv + old_size, -1);
1365   }
1366
1367   return TRUE;
1368 }
1369
1370 static gboolean
1371 speex_streamheader_to_codecdata (const GValue * streamheader,
1372     GstMatroskaTrackContext * context)
1373 {
1374   GArray *bufarr;
1375   GValue *bufval;
1376   GstBuffer *buffer;
1377   guint old_size;
1378
1379   if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
1380     GST_WARNING ("No or invalid streamheader field in the caps");
1381     return FALSE;
1382   }
1383
1384   bufarr = g_value_peek_pointer (streamheader);
1385   if (bufarr->len != 2) {
1386     GST_WARNING ("Too few headers in streamheader field");
1387     return FALSE;
1388   }
1389
1390   context->xiph_headers_to_skip = bufarr->len + 1;
1391
1392   bufval = &g_array_index (bufarr, GValue, 0);
1393   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1394     GST_WARNING ("streamheaders array does not contain GstBuffers");
1395     return FALSE;
1396   }
1397
1398   buffer = g_value_peek_pointer (bufval);
1399
1400   if (gst_buffer_get_size (buffer) < 80
1401       || gst_buffer_memcmp (buffer, 0, "Speex   ", 8) != 0) {
1402     GST_WARNING ("Invalid streamheader for Speex");
1403     return FALSE;
1404   }
1405
1406   context->codec_priv_size = gst_buffer_get_size (buffer);
1407   context->codec_priv = g_malloc (context->codec_priv_size);
1408   gst_buffer_extract (buffer, 0, context->codec_priv, -1);
1409
1410   bufval = &g_array_index (bufarr, GValue, 1);
1411
1412   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1413     g_free (context->codec_priv);
1414     context->codec_priv = NULL;
1415     context->codec_priv_size = 0;
1416     GST_WARNING ("streamheaders array does not contain GstBuffers");
1417     return FALSE;
1418   }
1419
1420   buffer = g_value_peek_pointer (bufval);
1421
1422   old_size = context->codec_priv_size;
1423   context->codec_priv_size += gst_buffer_get_size (buffer);
1424   context->codec_priv = g_realloc (context->codec_priv,
1425       context->codec_priv_size);
1426   gst_buffer_extract (buffer, 0, (guint8 *) context->codec_priv + old_size, -1);
1427
1428   return TRUE;
1429 }
1430
1431 static const gchar *
1432 aac_codec_data_to_codec_id (GstBuffer * buf)
1433 {
1434   const gchar *result;
1435   guint8 profile;
1436
1437   /* default to MAIN */
1438   profile = 1;
1439
1440   if (gst_buffer_get_size (buf) >= 2) {
1441     gst_buffer_extract (buf, 0, &profile, 1);
1442     profile >>= 3;
1443   }
1444
1445   switch (profile) {
1446     case 1:
1447       result = "MAIN";
1448       break;
1449     case 2:
1450       result = "LC";
1451       break;
1452     case 3:
1453       result = "SSR";
1454       break;
1455     case 4:
1456       result = "LTP";
1457       break;
1458     default:
1459       GST_WARNING ("unknown AAC profile, defaulting to MAIN");
1460       result = "MAIN";
1461       break;
1462   }
1463
1464   return result;
1465 }
1466
1467 /**
1468  * gst_matroska_mux_audio_pad_setcaps:
1469  * @pad: Pad which got the caps.
1470  * @caps: New caps.
1471  *
1472  * Setcaps function for audio sink pad.
1473  *
1474  * Returns: #TRUE on success.
1475  */
1476 static gboolean
1477 gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
1478 {
1479   GstMatroskaTrackContext *context = NULL;
1480   GstMatroskaTrackAudioContext *audiocontext;
1481   GstMatroskaMux *mux;
1482   GstMatroskaPad *collect_pad;
1483   const gchar *mimetype;
1484   gint samplerate = 0, channels = 0;
1485   GstStructure *structure;
1486   const GValue *codec_data = NULL;
1487   GstBuffer *buf = NULL;
1488   const gchar *stream_format = NULL;
1489
1490   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
1491
1492   /* find context */
1493   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
1494   g_assert (collect_pad);
1495   context = collect_pad->track;
1496   g_assert (context);
1497   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO);
1498   audiocontext = (GstMatroskaTrackAudioContext *) context;
1499
1500   structure = gst_caps_get_structure (caps, 0);
1501   mimetype = gst_structure_get_name (structure);
1502
1503   /* general setup */
1504   gst_structure_get_int (structure, "rate", &samplerate);
1505   gst_structure_get_int (structure, "channels", &channels);
1506
1507   audiocontext->samplerate = samplerate;
1508   audiocontext->channels = channels;
1509   audiocontext->bitdepth = 0;
1510   context->default_duration = 0;
1511
1512   codec_data = gst_structure_get_value (structure, "codec_data");
1513   if (codec_data)
1514     buf = gst_value_get_buffer (codec_data);
1515
1516   /* TODO: - check if we handle all codecs by the spec, i.e. codec private
1517    *         data and other settings
1518    *       - add new formats
1519    */
1520
1521   if (!strcmp (mimetype, "audio/mpeg")) {
1522     gint mpegversion = 0;
1523
1524     gst_structure_get_int (structure, "mpegversion", &mpegversion);
1525     switch (mpegversion) {
1526       case 1:{
1527         gint layer;
1528         gint version = 1;
1529         gint spf;
1530
1531         gst_structure_get_int (structure, "layer", &layer);
1532
1533         if (!gst_structure_get_int (structure, "mpegaudioversion", &version)) {
1534           GST_WARNING_OBJECT (mux,
1535               "Unable to determine MPEG audio version, assuming 1");
1536           version = 1;
1537         }
1538
1539         if (layer == 1)
1540           spf = 384;
1541         else if (layer == 2)
1542           spf = 1152;
1543         else if (version == 2)
1544           spf = 576;
1545         else
1546           spf = 1152;
1547
1548         context->default_duration =
1549             gst_util_uint64_scale (GST_SECOND, spf, audiocontext->samplerate);
1550
1551         switch (layer) {
1552           case 1:
1553             context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1);
1554             break;
1555           case 2:
1556             context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2);
1557             break;
1558           case 3:
1559             context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3);
1560             break;
1561           default:
1562             goto refuse_caps;
1563         }
1564         break;
1565       }
1566       case 2:
1567       case 4:
1568         stream_format = gst_structure_get_string (structure, "stream-format");
1569         /* check this is raw aac */
1570         if (stream_format) {
1571           if (strcmp (stream_format, "raw") != 0) {
1572             GST_WARNING_OBJECT (mux, "AAC stream-format must be 'raw', not %s",
1573                 stream_format);
1574           }
1575         } else {
1576           GST_WARNING_OBJECT (mux, "AAC stream-format not specified, "
1577               "assuming 'raw'");
1578         }
1579
1580         if (buf) {
1581           if (mpegversion == 2)
1582             context->codec_id =
1583                 g_strdup_printf (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2 "%s",
1584                 aac_codec_data_to_codec_id (buf));
1585           else if (mpegversion == 4)
1586             context->codec_id =
1587                 g_strdup_printf (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4 "%s",
1588                 aac_codec_data_to_codec_id (buf));
1589           else
1590             g_assert_not_reached ();
1591         } else {
1592           GST_DEBUG_OBJECT (mux, "no AAC codec_data; not packetized");
1593           goto refuse_caps;
1594         }
1595         break;
1596       default:
1597         goto refuse_caps;
1598     }
1599   } else if (!strcmp (mimetype, "audio/x-raw")) {
1600     GstAudioInfo info;
1601
1602     gst_audio_info_init (&info);
1603     if (!gst_audio_info_from_caps (&info, caps)) {
1604       GST_DEBUG_OBJECT (mux,
1605           "broken caps, rejected by gst_audio_info_from_caps");
1606       goto refuse_caps;
1607     }
1608
1609     switch (GST_AUDIO_INFO_FORMAT (&info)) {
1610       case GST_AUDIO_FORMAT_U8:
1611       case GST_AUDIO_FORMAT_S16BE:
1612       case GST_AUDIO_FORMAT_S16LE:
1613       case GST_AUDIO_FORMAT_S24BE:
1614       case GST_AUDIO_FORMAT_S24LE:
1615       case GST_AUDIO_FORMAT_S32BE:
1616       case GST_AUDIO_FORMAT_S32LE:
1617         if (GST_AUDIO_INFO_WIDTH (&info) != GST_AUDIO_INFO_DEPTH (&info)) {
1618           GST_DEBUG_OBJECT (mux, "width must be same as depth!");
1619           goto refuse_caps;
1620         }
1621         if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info))
1622           context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
1623         else
1624           context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
1625         break;
1626
1627       case GST_AUDIO_FORMAT_F32LE:
1628       case GST_AUDIO_FORMAT_F64LE:
1629         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
1630         break;
1631
1632       default:
1633         GST_DEBUG_OBJECT (mux, "wrong format in raw audio caps");
1634         goto refuse_caps;
1635     }
1636
1637     audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
1638
1639   } else if (!strcmp (mimetype, "audio/x-vorbis")) {
1640     const GValue *streamheader;
1641
1642     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_VORBIS);
1643
1644     if (context->codec_priv != NULL) {
1645       g_free (context->codec_priv);
1646       context->codec_priv = NULL;
1647       context->codec_priv_size = 0;
1648     }
1649
1650     streamheader = gst_structure_get_value (structure, "streamheader");
1651     if (!vorbis_streamheader_to_codecdata (streamheader, context)) {
1652       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1653           ("vorbis stream headers missing or malformed"));
1654       goto refuse_caps;
1655     }
1656   } else if (!strcmp (mimetype, "audio/x-flac")) {
1657     const GValue *streamheader;
1658
1659     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_FLAC);
1660     if (context->codec_priv != NULL) {
1661       g_free (context->codec_priv);
1662       context->codec_priv = NULL;
1663       context->codec_priv_size = 0;
1664     }
1665
1666     streamheader = gst_structure_get_value (structure, "streamheader");
1667     if (!flac_streamheader_to_codecdata (streamheader, context)) {
1668       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1669           ("flac stream headers missing or malformed"));
1670       goto refuse_caps;
1671     }
1672   } else if (!strcmp (mimetype, "audio/x-speex")) {
1673     const GValue *streamheader;
1674
1675     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_SPEEX);
1676     if (context->codec_priv != NULL) {
1677       g_free (context->codec_priv);
1678       context->codec_priv = NULL;
1679       context->codec_priv_size = 0;
1680     }
1681
1682     streamheader = gst_structure_get_value (structure, "streamheader");
1683     if (!speex_streamheader_to_codecdata (streamheader, context)) {
1684       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1685           ("speex stream headers missing or malformed"));
1686       goto refuse_caps;
1687     }
1688   } else if (!strcmp (mimetype, "audio/x-ac3")) {
1689     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AC3);
1690   } else if (!strcmp (mimetype, "audio/x-eac3")) {
1691     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_EAC3);
1692   } else if (!strcmp (mimetype, "audio/x-dts")) {
1693     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_DTS);
1694   } else if (!strcmp (mimetype, "audio/x-tta")) {
1695     gint width;
1696
1697     /* TTA frame duration */
1698     context->default_duration = 1.04489795918367346939 * GST_SECOND;
1699
1700     gst_structure_get_int (structure, "width", &width);
1701     audiocontext->bitdepth = width;
1702     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_TTA);
1703
1704   } else if (!strcmp (mimetype, "audio/x-pn-realaudio")) {
1705     gint raversion;
1706     const GValue *mdpr_data;
1707
1708     gst_structure_get_int (structure, "raversion", &raversion);
1709     switch (raversion) {
1710       case 1:
1711         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
1712         break;
1713       case 2:
1714         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
1715         break;
1716       case 8:
1717         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
1718         break;
1719       default:
1720         goto refuse_caps;
1721     }
1722
1723     mdpr_data = gst_structure_get_value (structure, "mdpr_data");
1724     if (mdpr_data != NULL) {
1725       guint8 *priv_data = NULL;
1726       guint priv_data_size = 0;
1727
1728       GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
1729
1730       priv_data_size = gst_buffer_get_size (codec_data_buf);
1731       priv_data = g_malloc0 (priv_data_size);
1732
1733       gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
1734
1735       context->codec_priv = priv_data;
1736       context->codec_priv_size = priv_data_size;
1737     }
1738
1739   } else if (!strcmp (mimetype, "audio/x-wma")
1740       || !strcmp (mimetype, "audio/x-alaw")
1741       || !strcmp (mimetype, "audio/x-mulaw")) {
1742     guint8 *codec_priv;
1743     guint codec_priv_size;
1744     guint16 format = 0;
1745     gint block_align;
1746     gint bitrate;
1747
1748     if (samplerate == 0 || channels == 0) {
1749       GST_WARNING_OBJECT (mux, "Missing channels/samplerate on caps");
1750       goto refuse_caps;
1751     }
1752
1753     if (!strcmp (mimetype, "audio/x-wma")) {
1754       gint wmaversion;
1755       gint depth;
1756
1757       if (!gst_structure_get_int (structure, "wmaversion", &wmaversion)
1758           || !gst_structure_get_int (structure, "block_align", &block_align)
1759           || !gst_structure_get_int (structure, "bitrate", &bitrate)) {
1760         GST_WARNING_OBJECT (mux, "Missing wmaversion/block_align/bitrate"
1761             " on WMA caps");
1762         goto refuse_caps;
1763       }
1764
1765       switch (wmaversion) {
1766         case 1:
1767           format = GST_RIFF_WAVE_FORMAT_WMAV1;
1768           break;
1769         case 2:
1770           format = GST_RIFF_WAVE_FORMAT_WMAV2;
1771           break;
1772         case 3:
1773           format = GST_RIFF_WAVE_FORMAT_WMAV3;
1774           break;
1775         default:
1776           GST_WARNING_OBJECT (mux, "Unexpected WMA version: %d", wmaversion);
1777           goto refuse_caps;
1778       }
1779
1780       if (gst_structure_get_int (structure, "depth", &depth))
1781         audiocontext->bitdepth = depth;
1782     } else if (!strcmp (mimetype, "audio/x-alaw")
1783         || !strcmp (mimetype, "audio/x-mulaw")) {
1784       audiocontext->bitdepth = 8;
1785       if (!strcmp (mimetype, "audio/x-alaw"))
1786         format = GST_RIFF_WAVE_FORMAT_ALAW;
1787       else
1788         format = GST_RIFF_WAVE_FORMAT_MULAW;
1789
1790       block_align = channels;
1791       bitrate = block_align * samplerate;
1792     }
1793     g_assert (format != 0);
1794
1795     codec_priv_size = WAVEFORMATEX_SIZE;
1796     if (buf)
1797       codec_priv_size += gst_buffer_get_size (buf);
1798
1799     /* serialize waveformatex structure */
1800     codec_priv = g_malloc0 (codec_priv_size);
1801     GST_WRITE_UINT16_LE (codec_priv, format);
1802     GST_WRITE_UINT16_LE (codec_priv + 2, channels);
1803     GST_WRITE_UINT32_LE (codec_priv + 4, samplerate);
1804     GST_WRITE_UINT32_LE (codec_priv + 8, bitrate / 8);
1805     GST_WRITE_UINT16_LE (codec_priv + 12, block_align);
1806     GST_WRITE_UINT16_LE (codec_priv + 14, 0);
1807     if (buf)
1808       GST_WRITE_UINT16_LE (codec_priv + 16, gst_buffer_get_size (buf));
1809     else
1810       GST_WRITE_UINT16_LE (codec_priv + 16, 0);
1811
1812     /* process codec private/initialization data, if any */
1813     if (buf) {
1814       gst_buffer_extract (buf, 0,
1815           (guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
1816     }
1817
1818     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_ACM);
1819     context->codec_priv = (gpointer) codec_priv;
1820     context->codec_priv_size = codec_priv_size;
1821   }
1822
1823   return TRUE;
1824
1825   /* ERRORS */
1826 refuse_caps:
1827   {
1828     GST_WARNING_OBJECT (mux, "pad %s refused caps %" GST_PTR_FORMAT,
1829         GST_PAD_NAME (pad), caps);
1830     return FALSE;
1831   }
1832 }
1833
1834
1835 /**
1836  * gst_matroska_mux_subtitle_pad_setcaps:
1837  * @pad: Pad which got the caps.
1838  * @caps: New caps.
1839  *
1840  * Setcaps function for subtitle sink pad.
1841  *
1842  * Returns: #TRUE on success.
1843  */
1844 static gboolean
1845 gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
1846 {
1847   /* FIXME:
1848    * Consider this as boilerplate code for now. There is
1849    * no single subtitle creation element in GStreamer,
1850    * neither do I know how subtitling works at all. */
1851
1852   /* There is now (at least) one such alement (kateenc), and I'm going
1853      to handle it here and claim it works when it can be piped back
1854      through GStreamer and VLC */
1855
1856   GstMatroskaTrackContext *context = NULL;
1857   GstMatroskaTrackSubtitleContext *scontext;
1858   GstMatroskaMux *mux;
1859   GstMatroskaPad *collect_pad;
1860   const gchar *mimetype;
1861   GstStructure *structure;
1862
1863   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
1864
1865   /* find context */
1866   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
1867   g_assert (collect_pad);
1868   context = collect_pad->track;
1869   g_assert (context);
1870   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE);
1871   scontext = (GstMatroskaTrackSubtitleContext *) context;
1872
1873   structure = gst_caps_get_structure (caps, 0);
1874   mimetype = gst_structure_get_name (structure);
1875
1876   /* general setup */
1877   scontext->check_utf8 = 1;
1878   scontext->invalid_utf8 = 0;
1879   context->default_duration = 0;
1880
1881   /* TODO: - other format than Kate */
1882
1883   if (!strcmp (mimetype, "subtitle/x-kate")) {
1884     const GValue *streamheader;
1885
1886     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
1887
1888     if (context->codec_priv != NULL) {
1889       g_free (context->codec_priv);
1890       context->codec_priv = NULL;
1891       context->codec_priv_size = 0;
1892     }
1893
1894     streamheader = gst_structure_get_value (structure, "streamheader");
1895     if (!kate_streamheader_to_codecdata (streamheader, context)) {
1896       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1897           ("kate stream headers missing or malformed"));
1898       return FALSE;
1899     }
1900     return TRUE;
1901   }
1902
1903   return FALSE;
1904 }
1905
1906
1907 /**
1908  * gst_matroska_mux_request_new_pad:
1909  * @element: #GstMatroskaMux.
1910  * @templ: #GstPadTemplate.
1911  * @pad_name: New pad name.
1912  *
1913  * Request pad function for sink templates.
1914  *
1915  * Returns: New #GstPad.
1916  */
1917 static GstPad *
1918 gst_matroska_mux_request_new_pad (GstElement * element,
1919     GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
1920 {
1921   GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
1922   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
1923   GstMatroskaPad *collect_pad;
1924   GstMatroskamuxPad *newpad;
1925   gchar *name = NULL;
1926   const gchar *pad_name = NULL;
1927   GstMatroskaCapsFunc capsfunc = NULL;
1928   GstMatroskaTrackContext *context = NULL;
1929   gint pad_id;
1930
1931   if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
1932     /* don't mix named and unnamed pads, if the pad already exists we fail when
1933      * trying to add it */
1934     if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
1935       pad_name = req_name;
1936     } else {
1937       name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
1938       pad_name = name;
1939     }
1940     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
1941     context = (GstMatroskaTrackContext *)
1942         g_new0 (GstMatroskaTrackAudioContext, 1);
1943     context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
1944     context->name = g_strdup ("Audio");
1945   } else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
1946     /* don't mix named and unnamed pads, if the pad already exists we fail when
1947      * trying to add it */
1948     if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
1949       pad_name = req_name;
1950     } else {
1951       name = g_strdup_printf ("video_%u", mux->num_v_streams++);
1952       pad_name = name;
1953     }
1954     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
1955     context = (GstMatroskaTrackContext *)
1956         g_new0 (GstMatroskaTrackVideoContext, 1);
1957     context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
1958     context->name = g_strdup ("Video");
1959   } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%u")) {
1960     /* don't mix named and unnamed pads, if the pad already exists we fail when
1961      * trying to add it */
1962     if (req_name != NULL && sscanf (req_name, "subtitle_%u", &pad_id) == 1) {
1963       pad_name = req_name;
1964     } else {
1965       name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++);
1966       pad_name = name;
1967     }
1968     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
1969     context = (GstMatroskaTrackContext *)
1970         g_new0 (GstMatroskaTrackSubtitleContext, 1);
1971     context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
1972     context->name = g_strdup ("Subtitle");
1973   } else {
1974     GST_WARNING_OBJECT (mux, "This is not our template!");
1975     return NULL;
1976   }
1977
1978   newpad = g_object_new (GST_TYPE_MATROSKAMUX_PAD,
1979       "name", pad_name, "direction", templ->direction, "template", templ, NULL);
1980   g_free (name);
1981
1982   gst_matroskamux_pad_init (newpad);
1983   collect_pad = (GstMatroskaPad *)
1984       gst_collect_pads_add_pad (mux->collect, GST_PAD (newpad),
1985       sizeof (GstMatroskaPad),
1986       (GstCollectDataDestroyNotify) gst_matroska_pad_free);
1987
1988   collect_pad->track = context;
1989   gst_matroska_pad_reset (collect_pad, FALSE);
1990
1991   /* FIXME: hacked way to override/extend the event function of
1992    * GstCollectPads; because it sets its own event function giving the
1993    * element no access to events.
1994    * TODO GstCollectPads should really give its 'users' a clean chance to
1995    * properly handle events that are not meant for collectpads itself.
1996    * Perhaps a callback or so, though rejected (?) in #340060.
1997    * This would allow (clean) transcoding of info from demuxer/streams
1998    * to another muxer */
1999   mux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
2000   gst_pad_set_event_function (GST_PAD (newpad),
2001       GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event));
2002
2003   collect_pad->capsfunc = capsfunc;
2004   gst_pad_set_active (GST_PAD (newpad), TRUE);
2005   if (!gst_element_add_pad (element, GST_PAD (newpad)))
2006     goto pad_add_failed;
2007
2008   mux->num_streams++;
2009
2010   GST_DEBUG_OBJECT (newpad, "Added new request pad");
2011
2012   return GST_PAD (newpad);
2013
2014   /* ERROR cases */
2015 pad_add_failed:
2016   {
2017     GST_WARNING_OBJECT (mux, "Adding the new pad '%s' failed", pad_name);
2018     gst_object_unref (newpad);
2019     return NULL;
2020   }
2021 }
2022
2023 /**
2024  * gst_matroska_mux_release_pad:
2025  * @element: #GstMatroskaMux.
2026  * @pad: Pad to release.
2027  *
2028  * Release a previously requested pad.
2029 */
2030 static void
2031 gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
2032 {
2033   GstMatroskaMux *mux;
2034   GSList *walk;
2035
2036   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
2037
2038   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
2039     GstCollectData *cdata = (GstCollectData *) walk->data;
2040     GstMatroskaPad *collect_pad = (GstMatroskaPad *) cdata;
2041
2042     if (cdata->pad == pad) {
2043       GstClockTime min_dur;     /* observed minimum duration */
2044
2045       if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2046           GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2047         min_dur = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2048         if (collect_pad->duration < min_dur)
2049           collect_pad->duration = min_dur;
2050       }
2051
2052       if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
2053           mux->duration < collect_pad->duration)
2054         mux->duration = collect_pad->duration;
2055
2056       break;
2057     }
2058   }
2059
2060   gst_collect_pads_remove_pad (mux->collect, pad);
2061   if (gst_element_remove_pad (element, pad))
2062     mux->num_streams--;
2063 }
2064
2065
2066 /**
2067  * gst_matroska_mux_track_header:
2068  * @mux: #GstMatroskaMux
2069  * @context: Tack context.
2070  *
2071  * Write a track header.
2072  */
2073 static void
2074 gst_matroska_mux_track_header (GstMatroskaMux * mux,
2075     GstMatroskaTrackContext * context)
2076 {
2077   GstEbmlWrite *ebml = mux->ebml_write;
2078   guint64 master;
2079
2080   /* TODO: check if everything necessary is written and check default values */
2081
2082   /* track type goes before the type-specific stuff */
2083   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKNUMBER, context->num);
2084   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKTYPE, context->type);
2085
2086   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKUID,
2087       gst_matroska_mux_create_uid ());
2088   if (context->default_duration) {
2089     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKDEFAULTDURATION,
2090         context->default_duration);
2091   }
2092   if (context->language) {
2093     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKLANGUAGE,
2094         context->language);
2095   }
2096
2097   /* type-specific stuff */
2098   switch (context->type) {
2099     case GST_MATROSKA_TRACK_TYPE_VIDEO:{
2100       GstMatroskaTrackVideoContext *videocontext =
2101           (GstMatroskaTrackVideoContext *) context;
2102
2103       master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKVIDEO);
2104       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELWIDTH,
2105           videocontext->pixel_width);
2106       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELHEIGHT,
2107           videocontext->pixel_height);
2108       if (videocontext->display_width && videocontext->display_height) {
2109         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEODISPLAYWIDTH,
2110             videocontext->display_width);
2111         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEODISPLAYHEIGHT,
2112             videocontext->display_height);
2113       }
2114       if (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED)
2115         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOFLAGINTERLACED, 1);
2116       if (videocontext->fourcc) {
2117         guint32 fcc_le = GUINT32_TO_LE (videocontext->fourcc);
2118
2119         gst_ebml_write_binary (ebml, GST_MATROSKA_ID_VIDEOCOLOURSPACE,
2120             (gpointer) & fcc_le, 4);
2121       }
2122       gst_ebml_write_master_finish (ebml, master);
2123
2124       break;
2125     }
2126
2127     case GST_MATROSKA_TRACK_TYPE_AUDIO:{
2128       GstMatroskaTrackAudioContext *audiocontext =
2129           (GstMatroskaTrackAudioContext *) context;
2130
2131       master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKAUDIO);
2132       if (audiocontext->samplerate != 8000)
2133         gst_ebml_write_float (ebml, GST_MATROSKA_ID_AUDIOSAMPLINGFREQ,
2134             audiocontext->samplerate);
2135       if (audiocontext->channels != 1)
2136         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOCHANNELS,
2137             audiocontext->channels);
2138       if (audiocontext->bitdepth) {
2139         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOBITDEPTH,
2140             audiocontext->bitdepth);
2141       }
2142       gst_ebml_write_master_finish (ebml, master);
2143
2144       break;
2145     }
2146
2147     default:
2148       /* doesn't need type-specific data */
2149       break;
2150   }
2151
2152   gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CODECID, context->codec_id);
2153   if (context->codec_priv)
2154     gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
2155         context->codec_priv, context->codec_priv_size);
2156   /* FIXME: until we have a nice way of getting the codecname
2157    * out of the caps, I'm not going to enable this. Too much
2158    * (useless, double, boring) work... */
2159   /* TODO: Use value from tags if any */
2160   /*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
2161      context->codec_name); */
2162   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
2163 }
2164
2165
2166 /**
2167  * gst_matroska_mux_start:
2168  * @mux: #GstMatroskaMux
2169  *
2170  * Start a new matroska file (write headers etc...)
2171  */
2172 static void
2173 gst_matroska_mux_start (GstMatroskaMux * mux)
2174 {
2175   GstEbmlWrite *ebml = mux->ebml_write;
2176   const gchar *doctype;
2177   guint32 seekhead_id[] = { GST_MATROSKA_ID_SEGMENTINFO,
2178     GST_MATROSKA_ID_TRACKS,
2179     GST_MATROSKA_ID_CUES,
2180     GST_MATROSKA_ID_TAGS,
2181     0
2182   };
2183   guint64 master, child;
2184   GSList *collected;
2185   int i;
2186   guint tracknum = 1;
2187   GstClockTime duration = 0;
2188   guint32 segment_uid[4];
2189   GTimeVal time = { 0, 0 };
2190
2191   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
2192     ebml->caps = gst_caps_new_empty_simple ("video/webm");
2193   } else {
2194     ebml->caps = gst_caps_new_empty_simple ("video/x-matroska");
2195   }
2196   /* we start with a EBML header */
2197   doctype = mux->doctype;
2198   GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
2199       doctype, mux->doctype_version);
2200   gst_ebml_write_header (ebml, doctype, mux->doctype_version);
2201
2202   /* the rest of the header is cached */
2203   gst_ebml_write_set_cache (ebml, 0x1000);
2204
2205   /* start a segment */
2206   mux->segment_pos =
2207       gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENT);
2208   mux->segment_master = ebml->pos;
2209
2210   if (!mux->streamable) {
2211     /* seekhead (table of contents) - we set the positions later */
2212     mux->seekhead_pos = ebml->pos;
2213     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKHEAD);
2214     for (i = 0; seekhead_id[i] != 0; i++) {
2215       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKENTRY);
2216       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKID, seekhead_id[i]);
2217       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKPOSITION, -1);
2218       gst_ebml_write_master_finish (ebml, child);
2219     }
2220     gst_ebml_write_master_finish (ebml, master);
2221   }
2222
2223   if (mux->streamable) {
2224     const GstTagList *tags;
2225
2226     /* tags */
2227     tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2228
2229     if (tags != NULL && !gst_tag_list_is_empty (tags)) {
2230       guint64 master_tags, master_tag;
2231
2232       GST_DEBUG ("Writing tags");
2233
2234       /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2235       mux->tags_pos = ebml->pos;
2236       master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2237       master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2238       gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2239       gst_ebml_write_master_finish (ebml, master_tag);
2240       gst_ebml_write_master_finish (ebml, master_tags);
2241     }
2242   }
2243
2244   /* segment info */
2245   mux->info_pos = ebml->pos;
2246   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);
2247   for (i = 0; i < 4; i++) {
2248     segment_uid[i] = g_random_int ();
2249   }
2250   gst_ebml_write_binary (ebml, GST_MATROSKA_ID_SEGMENTUID,
2251       (guint8 *) segment_uid, 16);
2252   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TIMECODESCALE, mux->time_scale);
2253   mux->duration_pos = ebml->pos;
2254   /* get duration */
2255   if (!mux->streamable) {
2256     for (collected = mux->collect->data; collected;
2257         collected = g_slist_next (collected)) {
2258       GstMatroskaPad *collect_pad;
2259       GstPad *thepad;
2260       gint64 trackduration;
2261
2262       collect_pad = (GstMatroskaPad *) collected->data;
2263       thepad = collect_pad->collect.pad;
2264
2265       /* Query the total length of the track. */
2266       GST_DEBUG_OBJECT (thepad, "querying peer duration");
2267       if (gst_pad_peer_query_duration (thepad, GST_FORMAT_TIME, &trackduration)) {
2268         GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
2269             GST_TIME_ARGS (trackduration));
2270         if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
2271           duration = (GstClockTime) trackduration;
2272         }
2273       }
2274     }
2275     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2276         gst_guint64_to_gdouble (duration) /
2277         gst_guint64_to_gdouble (mux->time_scale));
2278   }
2279   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_MUXINGAPP,
2280       "GStreamer plugin version " PACKAGE_VERSION);
2281   if (mux->writing_app && mux->writing_app[0]) {
2282     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, mux->writing_app);
2283   }
2284   g_get_current_time (&time);
2285   gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time.tv_sec);
2286   gst_ebml_write_master_finish (ebml, master);
2287
2288   /* tracks */
2289   mux->tracks_pos = ebml->pos;
2290   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKS);
2291
2292   for (collected = mux->collect->data; collected;
2293       collected = g_slist_next (collected)) {
2294     GstMatroskaPad *collect_pad;
2295     GstPad *thepad;
2296
2297     collect_pad = (GstMatroskaPad *) collected->data;
2298     thepad = collect_pad->collect.pad;
2299
2300     if (gst_pad_is_linked (thepad) && gst_pad_is_active (thepad) &&
2301         collect_pad->track->codec_id != 0) {
2302       collect_pad->track->num = tracknum++;
2303       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
2304       gst_matroska_mux_track_header (mux, collect_pad->track);
2305       gst_ebml_write_master_finish (ebml, child);
2306       /* some remaing pad/track setup */
2307       collect_pad->default_duration_scaled =
2308           gst_util_uint64_scale (collect_pad->track->default_duration,
2309           1, mux->time_scale);
2310     }
2311   }
2312   gst_ebml_write_master_finish (ebml, master);
2313
2314   /* lastly, flush the cache */
2315   gst_ebml_write_flush_cache (ebml, FALSE, 0);
2316 }
2317
2318 static void
2319 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
2320     gpointer data)
2321 {
2322   /* TODO: more sensible tag mappings */
2323   static const struct
2324   {
2325     const gchar *matroska_tagname;
2326     const gchar *gstreamer_tagname;
2327   }
2328   tag_conv[] = {
2329     {
2330     GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2331     GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
2332     GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2333     GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2334     GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2335     GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2336     GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2337     GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2338     GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2339     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2340     GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2341     GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2342     GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2343     GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2344     GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2345   };
2346   GstEbmlWrite *ebml = (GstEbmlWrite *) data;
2347   guint i;
2348   guint64 simpletag_master;
2349
2350   for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
2351     const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2352     const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2353
2354     if (strcmp (tagname_gst, tag) == 0) {
2355       GValue src = { 0, };
2356       gchar *dest;
2357
2358       if (!gst_tag_list_copy_value (&src, list, tag))
2359         break;
2360       if ((dest = gst_value_serialize (&src))) {
2361
2362         simpletag_master = gst_ebml_write_master_start (ebml,
2363             GST_MATROSKA_ID_SIMPLETAG);
2364         gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_TAGNAME, tagname_mkv);
2365         gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TAGSTRING, dest);
2366         gst_ebml_write_master_finish (ebml, simpletag_master);
2367         g_free (dest);
2368       } else {
2369         GST_WARNING ("Can't transform tag '%s' to string", tagname_mkv);
2370       }
2371       g_value_unset (&src);
2372       break;
2373     }
2374   }
2375 }
2376
2377
2378 /**
2379  * gst_matroska_mux_finish:
2380  * @mux: #GstMatroskaMux
2381  *
2382  * Finish a new matroska file (write index etc...)
2383  */
2384 static void
2385 gst_matroska_mux_finish (GstMatroskaMux * mux)
2386 {
2387   GstEbmlWrite *ebml = mux->ebml_write;
2388   guint64 pos;
2389   guint64 duration = 0;
2390   GSList *collected;
2391   const GstTagList *tags;
2392
2393   /* finish last cluster */
2394   if (mux->cluster) {
2395     gst_ebml_write_master_finish (ebml, mux->cluster);
2396   }
2397
2398   /* cues */
2399   if (mux->index != NULL) {
2400     guint n;
2401     guint64 master, pointentry_master, trackpos_master;
2402
2403     mux->cues_pos = ebml->pos;
2404     gst_ebml_write_set_cache (ebml, 12 + 41 * mux->num_indexes);
2405     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CUES);
2406
2407     for (n = 0; n < mux->num_indexes; n++) {
2408       GstMatroskaIndex *idx = &mux->index[n];
2409
2410       pointentry_master = gst_ebml_write_master_start (ebml,
2411           GST_MATROSKA_ID_POINTENTRY);
2412       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETIME,
2413           idx->time / mux->time_scale);
2414       trackpos_master = gst_ebml_write_master_start (ebml,
2415           GST_MATROSKA_ID_CUETRACKPOSITIONS);
2416       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETRACK, idx->track);
2417       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUECLUSTERPOSITION,
2418           idx->pos - mux->segment_master);
2419       gst_ebml_write_master_finish (ebml, trackpos_master);
2420       gst_ebml_write_master_finish (ebml, pointentry_master);
2421     }
2422
2423     gst_ebml_write_master_finish (ebml, master);
2424     gst_ebml_write_flush_cache (ebml, FALSE, GST_CLOCK_TIME_NONE);
2425   }
2426
2427   /* tags */
2428   tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2429
2430   if (tags != NULL && !gst_tag_list_is_empty (tags)) {
2431     guint64 master_tags, master_tag;
2432
2433     GST_DEBUG ("Writing tags");
2434
2435     /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2436     mux->tags_pos = ebml->pos;
2437     master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2438     master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2439     gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2440     gst_ebml_write_master_finish (ebml, master_tag);
2441     gst_ebml_write_master_finish (ebml, master_tags);
2442   }
2443
2444   /* update seekhead. We know that:
2445    * - a seekhead contains 4 entries.
2446    * - order of entries is as above.
2447    * - a seekhead has a 4-byte header + 8-byte length
2448    * - each entry is 2-byte master, 2-byte ID pointer,
2449    *     2-byte length pointer, all 8/1-byte length, 4-
2450    *     byte ID and 8-byte length pointer, where the
2451    *     length pointer starts at 20.
2452    * - all entries are local to the segment (so pos - segment_master).
2453    * - so each entry is at 12 + 20 + num * 28. */
2454   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
2455       mux->info_pos - mux->segment_master);
2456   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
2457       mux->tracks_pos - mux->segment_master);
2458   if (mux->index != NULL) {
2459     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 88,
2460         mux->cues_pos - mux->segment_master);
2461   } else {
2462     /* void'ify */
2463     guint64 my_pos = ebml->pos;
2464
2465     gst_ebml_write_seek (ebml, mux->seekhead_pos + 68);
2466     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2467     gst_ebml_write_seek (ebml, my_pos);
2468   }
2469   if (tags != NULL) {
2470     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 116,
2471         mux->tags_pos - mux->segment_master);
2472   } else {
2473     /* void'ify */
2474     guint64 my_pos = ebml->pos;
2475
2476     gst_ebml_write_seek (ebml, mux->seekhead_pos + 96);
2477     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2478     gst_ebml_write_seek (ebml, my_pos);
2479   }
2480
2481   /* update duration */
2482   /* first get the overall duration */
2483   /* a released track may have left a duration in here */
2484   duration = mux->duration;
2485   for (collected = mux->collect->data; collected;
2486       collected = g_slist_next (collected)) {
2487     GstMatroskaPad *collect_pad;
2488     GstClockTime min_duration;  /* observed minimum duration */
2489
2490     collect_pad = (GstMatroskaPad *) collected->data;
2491
2492     GST_DEBUG_OBJECT (mux,
2493         "Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
2494         " end ts %" GST_TIME_FORMAT, collect_pad,
2495         GST_TIME_ARGS (collect_pad->start_ts),
2496         GST_TIME_ARGS (collect_pad->end_ts));
2497
2498     if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2499         GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2500       min_duration =
2501           GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2502       if (collect_pad->duration < min_duration)
2503         collect_pad->duration = min_duration;
2504       GST_DEBUG_OBJECT (collect_pad,
2505           "final track duration: %" GST_TIME_FORMAT,
2506           GST_TIME_ARGS (collect_pad->duration));
2507     }
2508
2509     if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
2510         duration < collect_pad->duration)
2511       duration = collect_pad->duration;
2512   }
2513   if (duration != 0) {
2514     GST_DEBUG_OBJECT (mux, "final total duration: %" GST_TIME_FORMAT,
2515         GST_TIME_ARGS (duration));
2516     pos = mux->ebml_write->pos;
2517     gst_ebml_write_seek (ebml, mux->duration_pos);
2518     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2519         gst_guint64_to_gdouble (duration) /
2520         gst_guint64_to_gdouble (mux->time_scale));
2521     gst_ebml_write_seek (ebml, pos);
2522   } else {
2523     /* void'ify */
2524     guint64 my_pos = ebml->pos;
2525
2526     gst_ebml_write_seek (ebml, mux->duration_pos);
2527     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 8);
2528     gst_ebml_write_seek (ebml, my_pos);
2529   }
2530   GST_DEBUG_OBJECT (mux, "finishing segment");
2531   /* finish segment - this also writes element length */
2532   gst_ebml_write_master_finish (ebml, mux->segment_pos);
2533 }
2534
2535
2536 /**
2537  * gst_matroska_mux_best_pad:
2538  * @mux: #GstMatroskaMux
2539  * @popped: True if at least one buffer was popped from #GstCollectPads
2540  *
2541  * Find a pad with the oldest data
2542  * (data from this pad should be written first).
2543  *
2544  * Returns: Selected pad.
2545  */
2546 static GstMatroskaPad *
2547 gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
2548 {
2549   GSList *collected;
2550   GstMatroskaPad *best = NULL;
2551
2552   *popped = FALSE;
2553   for (collected = mux->collect->data; collected;
2554       collected = g_slist_next (collected)) {
2555     GstMatroskaPad *collect_pad;
2556
2557     collect_pad = (GstMatroskaPad *) collected->data;
2558     /* fetch a new buffer if needed */
2559     if (collect_pad->buffer == NULL) {
2560       collect_pad->buffer = gst_collect_pads_pop (mux->collect,
2561           (GstCollectData *) collect_pad);
2562
2563       if (collect_pad->buffer != NULL) {
2564         GstClockTime time;
2565
2566         *popped = TRUE;
2567         /* convert to running time */
2568         time = GST_BUFFER_TIMESTAMP (collect_pad->buffer);
2569         /* invalid should pass */
2570         if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
2571           time = gst_segment_to_running_time (&collect_pad->collect.segment,
2572               GST_FORMAT_TIME, time);
2573           if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
2574             GST_DEBUG_OBJECT (mux, "clipping buffer on pad %s outside segment",
2575                 GST_PAD_NAME (collect_pad->collect.pad));
2576             gst_buffer_unref (collect_pad->buffer);
2577             collect_pad->buffer = NULL;
2578             return NULL;
2579           } else {
2580             GST_LOG_OBJECT (mux, "buffer ts %" GST_TIME_FORMAT " -> %"
2581                 GST_TIME_FORMAT " running time",
2582                 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (collect_pad->buffer)),
2583                 GST_TIME_ARGS (time));
2584             collect_pad->buffer =
2585                 gst_buffer_make_writable (collect_pad->buffer);
2586             GST_BUFFER_TIMESTAMP (collect_pad->buffer) = time;
2587           }
2588         }
2589       }
2590     }
2591
2592     /* if we have a buffer check if it is better then the current best one */
2593     if (collect_pad->buffer != NULL) {
2594       if (best == NULL || !GST_BUFFER_TIMESTAMP_IS_VALID (collect_pad->buffer)
2595           || (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)
2596               && GST_BUFFER_TIMESTAMP (collect_pad->buffer) <
2597               GST_BUFFER_TIMESTAMP (best->buffer))) {
2598         best = collect_pad;
2599       }
2600     }
2601   }
2602
2603   return best;
2604 }
2605
2606 /**
2607  * gst_matroska_mux_buffer_header:
2608  * @track: Track context.
2609  * @relative_timestamp: relative timestamp of the buffer
2610  * @flags: Buffer flags.
2611  *
2612  * Create a buffer containing buffer header.
2613  *
2614  * Returns: New buffer.
2615  */
2616 static GstBuffer *
2617 gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
2618     gint16 relative_timestamp, int flags)
2619 {
2620   GstBuffer *hdr;
2621   guint8 *data = g_malloc (4);
2622
2623   hdr = gst_buffer_new_wrapped (data, 4);
2624   /* track num - FIXME: what if num >= 0x80 (unlikely)? */
2625   data[0] = track->num | 0x80;
2626   /* time relative to clustertime */
2627   GST_WRITE_UINT16_BE (data + 1, relative_timestamp);
2628
2629   /* flags */
2630   data[3] = flags;
2631
2632   return hdr;
2633 }
2634
2635 #define DIRAC_PARSE_CODE_SEQUENCE_HEADER 0x00
2636 #define DIRAC_PARSE_CODE_END_OF_SEQUENCE 0x10
2637 #define DIRAC_PARSE_CODE_IS_PICTURE(x) ((x & 0x08) != 0)
2638
2639 static GstBuffer *
2640 gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
2641     GstMatroskaPad * collect_pad, GstBuffer * buf)
2642 {
2643   GstMatroskaTrackVideoContext *ctx =
2644       (GstMatroskaTrackVideoContext *) collect_pad->track;
2645   guint8 *buf_data, *data;
2646   gsize size;
2647   guint8 parse_code;
2648   guint32 next_parse_offset;
2649   GstBuffer *ret = NULL;
2650   gboolean is_muxing_unit = FALSE;
2651
2652   buf_data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
2653   data = buf_data;
2654
2655   if (size < 13) {
2656     gst_buffer_unmap (buf, buf_data, -1);
2657     gst_buffer_unref (buf);
2658     return ret;
2659   }
2660
2661   /* Check if this buffer contains a picture or end-of-sequence packet */
2662   while (size >= 13) {
2663     if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) {
2664       gst_buffer_unmap (buf, buf_data, -1);
2665       gst_buffer_unref (buf);
2666       return ret;
2667     }
2668
2669     parse_code = GST_READ_UINT8 (data + 4);
2670     if (parse_code == DIRAC_PARSE_CODE_SEQUENCE_HEADER) {
2671       if (ctx->dirac_unit) {
2672         gst_buffer_unref (ctx->dirac_unit);
2673         ctx->dirac_unit = NULL;
2674       }
2675     } else if (DIRAC_PARSE_CODE_IS_PICTURE (parse_code) ||
2676         parse_code == DIRAC_PARSE_CODE_END_OF_SEQUENCE) {
2677       is_muxing_unit = TRUE;
2678       break;
2679     }
2680
2681     next_parse_offset = GST_READ_UINT32_BE (data + 5);
2682
2683     if (G_UNLIKELY (next_parse_offset == 0 || next_parse_offset > size))
2684       break;
2685
2686     data += next_parse_offset;
2687     size -= next_parse_offset;
2688   }
2689
2690   if (ctx->dirac_unit)
2691     ctx->dirac_unit = gst_buffer_join (ctx->dirac_unit, gst_buffer_ref (buf));
2692   else
2693     ctx->dirac_unit = gst_buffer_ref (buf);
2694
2695   gst_buffer_unmap (buf, buf_data, -1);
2696
2697   if (is_muxing_unit) {
2698     ret = gst_buffer_make_writable (ctx->dirac_unit);
2699     ctx->dirac_unit = NULL;
2700     gst_buffer_copy_into (ret, buf,
2701         GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2702     gst_buffer_unref (buf);
2703   } else {
2704     gst_buffer_unref (buf);
2705     ret = NULL;
2706   }
2707
2708   return ret;
2709 }
2710
2711 static void
2712 gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
2713 {
2714   GstCaps *caps;
2715   GstStructure *s;
2716   GValue streamheader = { 0 };
2717   GValue bufval = { 0 };
2718   GstBuffer *streamheader_buffer;
2719   GstEbmlWrite *ebml = mux->ebml_write;
2720
2721   streamheader_buffer = gst_ebml_stop_streamheader (ebml);
2722   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
2723     caps = gst_caps_new_empty_simple ("video/webm");
2724   } else {
2725     caps = gst_caps_new_empty_simple ("video/x-matroska");
2726   }
2727   s = gst_caps_get_structure (caps, 0);
2728   g_value_init (&streamheader, GST_TYPE_ARRAY);
2729   g_value_init (&bufval, GST_TYPE_BUFFER);
2730   GST_BUFFER_FLAG_SET (streamheader_buffer, GST_BUFFER_FLAG_IN_CAPS);
2731   gst_value_set_buffer (&bufval, streamheader_buffer);
2732   gst_value_array_append_value (&streamheader, &bufval);
2733   g_value_unset (&bufval);
2734   gst_structure_set_value (s, "streamheader", &streamheader);
2735   g_value_unset (&streamheader);
2736   gst_caps_replace (&ebml->caps, caps);
2737   gst_buffer_unref (streamheader_buffer);
2738   gst_caps_unref (caps);
2739 }
2740
2741 /**
2742  * gst_matroska_mux_write_data:
2743  * @mux: #GstMatroskaMux
2744  * @collect_pad: #GstMatroskaPad with the data
2745  *
2746  * Write collected data (called from gst_matroska_mux_collected).
2747  *
2748  * Returns: Result of the gst_pad_push issued to write the data.
2749  */
2750 static GstFlowReturn
2751 gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
2752 {
2753   GstEbmlWrite *ebml = mux->ebml_write;
2754   GstBuffer *buf, *hdr;
2755   guint64 blockgroup;
2756   gboolean write_duration;
2757   gint16 relative_timestamp;
2758   gint64 relative_timestamp64;
2759   guint64 block_duration;
2760   gboolean is_video_keyframe = FALSE;
2761   GstMatroskamuxPad *pad;
2762
2763   /* write data */
2764   buf = collect_pad->buffer;
2765   collect_pad->buffer = NULL;
2766   pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
2767
2768   /* vorbis/theora headers are retrieved from caps and put in CodecPrivate */
2769   if (collect_pad->track->xiph_headers_to_skip > 0) {
2770     GST_LOG_OBJECT (collect_pad->collect.pad, "dropping streamheader buffer");
2771     gst_buffer_unref (buf);
2772     --collect_pad->track->xiph_headers_to_skip;
2773     return GST_FLOW_OK;
2774   }
2775
2776   /* for dirac we have to queue up everything up to a picture unit */
2777   if (collect_pad->track->codec_id != NULL &&
2778       strcmp (collect_pad->track->codec_id,
2779           GST_MATROSKA_CODEC_ID_VIDEO_DIRAC) == 0) {
2780     buf = gst_matroska_mux_handle_dirac_packet (mux, collect_pad, buf);
2781     if (!buf)
2782       return GST_FLOW_OK;
2783   }
2784
2785   /* hm, invalid timestamp (due to --to be fixed--- element upstream);
2786    * this would wreak havoc with time stored in matroska file */
2787   /* TODO: maybe calculate a timestamp by using the previous timestamp
2788    * and default duration */
2789   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2790     GST_WARNING_OBJECT (collect_pad->collect.pad,
2791         "Invalid buffer timestamp; dropping buffer");
2792     gst_buffer_unref (buf);
2793     return GST_FLOW_OK;
2794   }
2795
2796   /* set the timestamp for outgoing buffers */
2797   ebml->timestamp = GST_BUFFER_TIMESTAMP (buf);
2798
2799   if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
2800       !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
2801     GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT,
2802         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
2803     is_video_keyframe = TRUE;
2804   }
2805
2806   if (mux->cluster) {
2807     /* start a new cluster at every keyframe, at every GstForceKeyUnit event,
2808      * or when we may be reaching the limit of the relative timestamp */
2809     if (mux->cluster_time +
2810         mux->max_cluster_duration < GST_BUFFER_TIMESTAMP (buf)
2811         || is_video_keyframe || mux->force_key_unit_event) {
2812       if (!mux->streamable)
2813         gst_ebml_write_master_finish (ebml, mux->cluster);
2814
2815       /* Forward the GstForceKeyUnit event after finishing the cluster */
2816       if (mux->force_key_unit_event) {
2817         gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
2818         mux->force_key_unit_event = NULL;
2819       }
2820
2821       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
2822       mux->cluster_pos = ebml->pos;
2823       gst_ebml_write_set_cache (ebml, 0x20);
2824       mux->cluster =
2825           gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2826       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2827           gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
2828               mux->time_scale));
2829       GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
2830           gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
2831               mux->time_scale));
2832       gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
2833       mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2834       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
2835           mux->prev_cluster_size);
2836     }
2837   } else {
2838     /* first cluster */
2839
2840     mux->cluster_pos = ebml->pos;
2841     gst_ebml_write_set_cache (ebml, 0x20);
2842     mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2843     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2844         gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1, mux->time_scale));
2845     gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
2846     mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2847   }
2848
2849   /* update duration of this track */
2850   if (GST_BUFFER_DURATION_IS_VALID (buf))
2851     collect_pad->duration += GST_BUFFER_DURATION (buf);
2852
2853   /* We currently write index entries for all video tracks or for the audio
2854    * track in a single-track audio file.  This could be improved by keeping the
2855    * index only for the *first* video track. */
2856
2857   /* TODO: index is useful for every track, should contain the number of
2858    * the block in the cluster which contains the timestamp, should also work
2859    * for files with multiple audio tracks.
2860    */
2861   if (!mux->streamable &&
2862       (is_video_keyframe ||
2863           ((collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO) &&
2864               (mux->num_streams == 1)))) {
2865     gint last_idx = -1;
2866
2867     if (mux->min_index_interval != 0) {
2868       for (last_idx = mux->num_indexes - 1; last_idx >= 0; last_idx--) {
2869         if (mux->index[last_idx].track == collect_pad->track->num)
2870           break;
2871       }
2872     }
2873
2874     if (last_idx < 0 || mux->min_index_interval == 0 ||
2875         (GST_CLOCK_DIFF (mux->index[last_idx].time, GST_BUFFER_TIMESTAMP (buf))
2876             >= mux->min_index_interval)) {
2877       GstMatroskaIndex *idx;
2878
2879       if (mux->num_indexes % 32 == 0) {
2880         mux->index = g_renew (GstMatroskaIndex, mux->index,
2881             mux->num_indexes + 32);
2882       }
2883       idx = &mux->index[mux->num_indexes++];
2884
2885       idx->pos = mux->cluster_pos;
2886       idx->time = GST_BUFFER_TIMESTAMP (buf);
2887       idx->track = collect_pad->track->num;
2888     }
2889   }
2890
2891   /* Check if the duration differs from the default duration. */
2892   write_duration = FALSE;
2893   block_duration = 0;
2894   if (pad->frame_duration && GST_BUFFER_DURATION_IS_VALID (buf)) {
2895     block_duration = gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
2896         1, mux->time_scale);
2897
2898     /* small difference should be ok. */
2899     if (block_duration > collect_pad->default_duration_scaled + 1 ||
2900         block_duration < collect_pad->default_duration_scaled - 1) {
2901       write_duration = TRUE;
2902     }
2903   }
2904
2905   /* write the block, for doctype v2 use SimpleBlock if possible
2906    * one slice (*breath*).
2907    * FIXME: Need to do correct lacing! */
2908   relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time;
2909   if (relative_timestamp64 >= 0) {
2910     /* round the timestamp */
2911     relative_timestamp64 += gst_util_uint64_scale (mux->time_scale, 1, 2);
2912   } else {
2913     /* round the timestamp */
2914     relative_timestamp64 -= gst_util_uint64_scale (mux->time_scale, 1, 2);
2915   }
2916   relative_timestamp = gst_util_uint64_scale (relative_timestamp64, 1,
2917       mux->time_scale);
2918   if (mux->doctype_version > 1 && !write_duration) {
2919     int flags =
2920         GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : 0x80;
2921
2922     hdr =
2923         gst_matroska_mux_create_buffer_header (collect_pad->track,
2924         relative_timestamp, flags);
2925     gst_ebml_write_set_cache (ebml, 0x40);
2926     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
2927         gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
2928     gst_ebml_write_buffer (ebml, hdr);
2929     gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
2930     gst_ebml_write_buffer (ebml, buf);
2931
2932     return gst_ebml_last_write_result (ebml);
2933   } else {
2934     gst_ebml_write_set_cache (ebml, gst_buffer_get_size (buf) * 2);
2935     /* write and call order slightly unnatural,
2936      * but avoids seek and minizes pushing */
2937     blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
2938     hdr =
2939         gst_matroska_mux_create_buffer_header (collect_pad->track,
2940         relative_timestamp, 0);
2941     if (write_duration)
2942       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
2943     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
2944         gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
2945     gst_ebml_write_buffer (ebml, hdr);
2946     gst_ebml_write_master_finish_full (ebml, blockgroup,
2947         gst_buffer_get_size (buf));
2948     gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
2949     gst_ebml_write_buffer (ebml, buf);
2950
2951     return gst_ebml_last_write_result (ebml);
2952   }
2953 }
2954
2955
2956 /**
2957  * gst_matroska_mux_collected:
2958  * @pads: #GstCollectPads
2959  * @uuser_data: #GstMatroskaMux
2960  *
2961  * Collectpads callback.
2962  *
2963  * Returns: #GstFlowReturn
2964  */
2965 static GstFlowReturn
2966 gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
2967 {
2968   GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
2969   GstEbmlWrite *ebml = mux->ebml_write;
2970   GstMatroskaPad *best;
2971   gboolean popped;
2972   GstFlowReturn ret = GST_FLOW_OK;
2973
2974   GST_DEBUG_OBJECT (mux, "Collected pads");
2975
2976   /* start with a header */
2977   if (mux->state == GST_MATROSKA_MUX_STATE_START) {
2978     if (mux->collect->data == NULL) {
2979       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
2980           ("No input streams configured"));
2981       return GST_FLOW_ERROR;
2982     }
2983     mux->state = GST_MATROSKA_MUX_STATE_HEADER;
2984     gst_ebml_start_streamheader (ebml);
2985     gst_matroska_mux_start (mux);
2986     gst_matroska_mux_stop_streamheader (mux);
2987     mux->state = GST_MATROSKA_MUX_STATE_DATA;
2988   }
2989
2990   do {
2991     /* which stream to write from? */
2992     best = gst_matroska_mux_best_pad (mux, &popped);
2993
2994     /* if there is no best pad, we have reached EOS */
2995     if (best == NULL) {
2996       /* buffer popped, but none returned means it was clipped */
2997       if (popped)
2998         break;
2999       GST_DEBUG_OBJECT (mux, "No best pad finishing...");
3000       if (!mux->streamable) {
3001         gst_matroska_mux_finish (mux);
3002       } else {
3003         GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
3004       }
3005       gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
3006       ret = GST_FLOW_UNEXPECTED;
3007       break;
3008     }
3009     GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
3010         GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
3011         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (best->buffer)),
3012         GST_TIME_ARGS (GST_BUFFER_DURATION (best->buffer)));
3013
3014     /* make note of first and last encountered timestamps, so we can calculate
3015      * the actual duration later when we send an updated header on eos */
3016     if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
3017       GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
3018       GstClockTime end_ts = start_ts;
3019
3020       if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
3021         end_ts += GST_BUFFER_DURATION (best->buffer);
3022       else if (best->track->default_duration)
3023         end_ts += best->track->default_duration;
3024
3025       if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
3026         best->end_ts = end_ts;
3027
3028       if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
3029               start_ts < best->start_ts))
3030         best->start_ts = start_ts;
3031     }
3032
3033     /* write one buffer */
3034     ret = gst_matroska_mux_write_data (mux, best);
3035   } while (ret == GST_FLOW_OK && !popped);
3036
3037   return ret;
3038 }
3039
3040
3041 /**
3042  * gst_matroska_mux_change_state:
3043  * @element: #GstMatroskaMux
3044  * @transition: State change transition.
3045  *
3046  * Change the muxer state.
3047  *
3048  * Returns: #GstStateChangeReturn
3049  */
3050 static GstStateChangeReturn
3051 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
3052 {
3053   GstStateChangeReturn ret;
3054   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
3055
3056   switch (transition) {
3057     case GST_STATE_CHANGE_NULL_TO_READY:
3058       break;
3059     case GST_STATE_CHANGE_READY_TO_PAUSED:
3060       gst_collect_pads_start (mux->collect);
3061       break;
3062     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3063       break;
3064     case GST_STATE_CHANGE_PAUSED_TO_READY:
3065       gst_collect_pads_stop (mux->collect);
3066       break;
3067     default:
3068       break;
3069   }
3070
3071   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3072
3073   switch (transition) {
3074     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3075       break;
3076     case GST_STATE_CHANGE_PAUSED_TO_READY:
3077       gst_matroska_mux_reset (GST_ELEMENT (mux));
3078       break;
3079     case GST_STATE_CHANGE_READY_TO_NULL:
3080       break;
3081     default:
3082       break;
3083   }
3084
3085   return ret;
3086 }
3087
3088 static void
3089 gst_matroska_mux_set_property (GObject * object,
3090     guint prop_id, const GValue * value, GParamSpec * pspec)
3091 {
3092   GstMatroskaMux *mux;
3093
3094   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3095   mux = GST_MATROSKA_MUX (object);
3096
3097   switch (prop_id) {
3098     case ARG_WRITING_APP:
3099       if (!g_value_get_string (value)) {
3100         GST_WARNING_OBJECT (mux, "writing-app property can not be NULL");
3101         break;
3102       }
3103       g_free (mux->writing_app);
3104       mux->writing_app = g_value_dup_string (value);
3105       break;
3106     case ARG_DOCTYPE_VERSION:
3107       mux->doctype_version = g_value_get_int (value);
3108       break;
3109     case ARG_MIN_INDEX_INTERVAL:
3110       mux->min_index_interval = g_value_get_int64 (value);
3111       break;
3112     case ARG_STREAMABLE:
3113       mux->streamable = g_value_get_boolean (value);
3114       break;
3115     default:
3116       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3117       break;
3118   }
3119 }
3120
3121 static void
3122 gst_matroska_mux_get_property (GObject * object,
3123     guint prop_id, GValue * value, GParamSpec * pspec)
3124 {
3125   GstMatroskaMux *mux;
3126
3127   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3128   mux = GST_MATROSKA_MUX (object);
3129
3130   switch (prop_id) {
3131     case ARG_WRITING_APP:
3132       g_value_set_string (value, mux->writing_app);
3133       break;
3134     case ARG_DOCTYPE_VERSION:
3135       g_value_set_int (value, mux->doctype_version);
3136       break;
3137     case ARG_MIN_INDEX_INTERVAL:
3138       g_value_set_int64 (value, mux->min_index_interval);
3139       break;
3140     case ARG_STREAMABLE:
3141       g_value_set_boolean (value, mux->streamable);
3142       break;
3143     default:
3144       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3145       break;
3146   }
3147 }