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