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