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