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