matroskamux: Only forward the event when we didn't handle it ourselves
[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
739   mux = GST_MATROSKA_MUX (user_data);
740   collect_pad = (GstMatroskaPad *) data;
741   pad = data->pad;
742   context = collect_pad->track;
743   g_assert (context);
744
745   switch (GST_EVENT_TYPE (event)) {
746     case GST_EVENT_CAPS:{
747       GstCaps *caps;
748
749       collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
750       gst_event_parse_caps (event, &caps);
751
752       collect_pad->capsfunc (pad, caps);
753       gst_event_unref (event);
754       event = NULL;
755       break;
756     }
757     case GST_EVENT_TAG:{
758       gchar *lang = NULL;
759
760       GST_DEBUG_OBJECT (mux, "received tag event");
761       gst_event_parse_tag (event, &list);
762
763       /* Matroska wants ISO 639-2B code, taglist most likely contains 639-1 */
764       if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) {
765         const gchar *lang_code;
766
767         lang_code = gst_tag_get_language_code_iso_639_2B (lang);
768         if (lang_code) {
769           GST_INFO_OBJECT (pad, "Setting language to '%s'", lang_code);
770           context->language = g_strdup (lang_code);
771         } else {
772           GST_WARNING_OBJECT (pad, "Did not get language code for '%s'", lang);
773         }
774         g_free (lang);
775       }
776
777       /* FIXME: what about stream-specific tags? */
778       gst_tag_setter_merge_tags (GST_TAG_SETTER (mux), list,
779           gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (mux)));
780
781       gst_event_unref (event);
782       /* handled this, don't want collectpads to forward it downstream */
783       event = NULL;
784       break;
785     }
786     case GST_EVENT_SEGMENT:{
787       const GstSegment *segment;
788
789       gst_event_parse_segment (event, &segment);
790       if (segment->format != GST_FORMAT_TIME) {
791         gst_event_unref (event);
792         event = NULL;
793       }
794       break;
795     }
796     case GST_EVENT_CUSTOM_DOWNSTREAM:{
797       const GstStructure *structure;
798
799       structure = gst_event_get_structure (event);
800       if (gst_structure_has_name (structure, "GstForceKeyUnit")) {
801         gst_event_replace (&mux->force_key_unit_event, NULL);
802         mux->force_key_unit_event = event;
803         event = NULL;
804       } else if (gst_structure_has_name (structure, "application/x-gst-dvd") &&
805           !strcmp ("dvd-spu-clut-change",
806               gst_structure_get_string (structure, "event"))) {
807         gchar name[16];
808         gint i, value;
809         guint clut[16];
810
811         GST_DEBUG_OBJECT (pad, "New DVD colour table received");
812         if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE) {
813           GST_DEBUG_OBJECT (pad, "... discarding");
814           break;
815         }
816         /* first transform event data into table form */
817         for (i = 0; i < 16; i++) {
818           g_snprintf (name, sizeof (name), "clut%02d", i);
819           if (!gst_structure_get_int (structure, name, &value)) {
820             GST_ERROR_OBJECT (mux, "dvd-spu-clut-change event did not "
821                 "contain %s field", name);
822             break;
823           }
824           clut[i] = value;
825         }
826
827         /* transform into private data for stream; text form */
828         gst_matroska_mux_build_vobsub_private (context, clut);
829       }
830       break;
831     }
832     default:
833       break;
834   }
835
836   /* now GstCollectPads2 can take care of the rest, e.g. EOS */
837   return (event == NULL);
838 }
839
840 static void
841 gst_matroska_mux_set_codec_id (GstMatroskaTrackContext * context,
842     const char *id)
843 {
844   g_assert (context && id);
845   if (context->codec_id)
846     g_free (context->codec_id);
847   context->codec_id = g_strdup (id);
848 }
849
850 /**
851  * gst_matroska_mux_video_pad_setcaps:
852  * @pad: Pad which got the caps.
853  * @caps: New caps.
854  *
855  * Setcaps function for video sink pad.
856  *
857  * Returns: #TRUE on success.
858  */
859 static gboolean
860 gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
861 {
862   GstMatroskaTrackContext *context = NULL;
863   GstMatroskaTrackVideoContext *videocontext;
864   GstMatroskaMux *mux;
865   GstMatroskaPad *collect_pad;
866   GstStructure *structure;
867   const gchar *mimetype;
868   const GValue *value = NULL;
869   GstBuffer *codec_buf = NULL;
870   gint width, height, pixel_width, pixel_height;
871   gint fps_d, fps_n;
872   gboolean interlaced = FALSE;
873
874   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
875
876   /* find context */
877   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
878   g_assert (collect_pad);
879   context = collect_pad->track;
880   g_assert (context);
881   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO);
882   videocontext = (GstMatroskaTrackVideoContext *) context;
883
884   /* gst -> matroska ID'ing */
885   structure = gst_caps_get_structure (caps, 0);
886
887   mimetype = gst_structure_get_name (structure);
888
889   if (gst_structure_get_boolean (structure, "interlaced", &interlaced)
890       && interlaced)
891     context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
892
893   if (!strcmp (mimetype, "video/x-theora")) {
894     /* we'll extract the details later from the theora identification header */
895     goto skip_details;
896   }
897
898   /* get general properties */
899   /* spec says it is mandatory */
900   if (!gst_structure_get_int (structure, "width", &width) ||
901       !gst_structure_get_int (structure, "height", &height))
902     goto refuse_caps;
903
904   videocontext->pixel_width = width;
905   videocontext->pixel_height = height;
906
907   /* set vp8 defaults or let user override it */
908   if (GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration_user == FALSE
909       && (!strcmp (mimetype, "video/x-vp8")))
910     GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration =
911         DEFAULT_PAD_FRAME_DURATION_VP8;
912
913   if (GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration
914       && gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)
915       && fps_n > 0) {
916     context->default_duration =
917         gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
918     GST_LOG_OBJECT (pad, "default duration = %" GST_TIME_FORMAT,
919         GST_TIME_ARGS (context->default_duration));
920   } else {
921     context->default_duration = 0;
922   }
923   if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
924           &pixel_width, &pixel_height)) {
925     if (pixel_width > pixel_height) {
926       videocontext->display_width = width * pixel_width / pixel_height;
927       videocontext->display_height = height;
928     } else if (pixel_width < pixel_height) {
929       videocontext->display_width = width;
930       videocontext->display_height = height * pixel_height / pixel_width;
931     } else {
932       videocontext->display_width = 0;
933       videocontext->display_height = 0;
934     }
935   } else {
936     videocontext->display_width = 0;
937     videocontext->display_height = 0;
938   }
939
940 skip_details:
941
942   videocontext->asr_mode = GST_MATROSKA_ASPECT_RATIO_MODE_FREE;
943   videocontext->fourcc = 0;
944
945   /* TODO: - check if we handle all codecs by the spec, i.e. codec private
946    *         data and other settings
947    *       - add new formats
948    */
949
950   /* extract codec_data, may turn out needed */
951   value = gst_structure_get_value (structure, "codec_data");
952   if (value)
953     codec_buf = (GstBuffer *) gst_value_get_buffer (value);
954
955   /* find type */
956   if (!strcmp (mimetype, "video/x-raw")) {
957     const gchar *fstr;
958     gst_matroska_mux_set_codec_id (context,
959         GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
960     fstr = gst_structure_get_string (structure, "format");
961     if (fstr && strlen (fstr) == 4)
962       videocontext->fourcc = GST_STR_FOURCC (fstr);
963   } else if (!strcmp (mimetype, "image/jpeg")) {
964     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
965   } else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
966       ||!strcmp (mimetype, "video/x-huffyuv")
967       || !strcmp (mimetype, "video/x-divx")
968       || !strcmp (mimetype, "video/x-dv")
969       || !strcmp (mimetype, "video/x-h263")
970       || !strcmp (mimetype, "video/x-msmpeg")
971       || !strcmp (mimetype, "video/x-wmv")
972       || !strcmp (mimetype, "image/jpeg")) {
973     gst_riff_strf_vids *bih;
974     gint size = sizeof (gst_riff_strf_vids);
975     guint32 fourcc = 0;
976
977     if (!strcmp (mimetype, "video/x-xvid"))
978       fourcc = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
979     else if (!strcmp (mimetype, "video/x-huffyuv"))
980       fourcc = GST_MAKE_FOURCC ('H', 'F', 'Y', 'U');
981     else if (!strcmp (mimetype, "video/x-dv"))
982       fourcc = GST_MAKE_FOURCC ('D', 'V', 'S', 'D');
983     else if (!strcmp (mimetype, "video/x-h263"))
984       fourcc = GST_MAKE_FOURCC ('H', '2', '6', '3');
985     else if (!strcmp (mimetype, "video/x-divx")) {
986       gint divxversion;
987
988       gst_structure_get_int (structure, "divxversion", &divxversion);
989       switch (divxversion) {
990         case 3:
991           fourcc = GST_MAKE_FOURCC ('D', 'I', 'V', '3');
992           break;
993         case 4:
994           fourcc = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
995           break;
996         case 5:
997           fourcc = GST_MAKE_FOURCC ('D', 'X', '5', '0');
998           break;
999       }
1000     } else if (!strcmp (mimetype, "video/x-msmpeg")) {
1001       gint msmpegversion;
1002
1003       gst_structure_get_int (structure, "msmpegversion", &msmpegversion);
1004       switch (msmpegversion) {
1005         case 41:
1006           fourcc = GST_MAKE_FOURCC ('M', 'P', 'G', '4');
1007           break;
1008         case 42:
1009           fourcc = GST_MAKE_FOURCC ('M', 'P', '4', '2');
1010           break;
1011         case 43:
1012           goto msmpeg43;
1013           break;
1014       }
1015     } else if (!strcmp (mimetype, "video/x-wmv")) {
1016       gint wmvversion;
1017       const gchar *fstr;
1018
1019       fstr = gst_structure_get_string (structure, "format");
1020       if (fstr && strlen (fstr) == 4) {
1021         fourcc = GST_STR_FOURCC (fstr);
1022       } else if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) {
1023         if (wmvversion == 2) {
1024           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '2');
1025         } else if (wmvversion == 1) {
1026           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '1');
1027         } else if (wmvversion == 3) {
1028           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
1029         }
1030       }
1031     } else if (!strcmp (mimetype, "image/jpeg")) {
1032       fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
1033     }
1034
1035     if (!fourcc)
1036       goto refuse_caps;
1037
1038     bih = g_new0 (gst_riff_strf_vids, 1);
1039     GST_WRITE_UINT32_LE (&bih->size, size);
1040     GST_WRITE_UINT32_LE (&bih->width, videocontext->pixel_width);
1041     GST_WRITE_UINT32_LE (&bih->height, videocontext->pixel_height);
1042     GST_WRITE_UINT32_LE (&bih->compression, fourcc);
1043     GST_WRITE_UINT16_LE (&bih->planes, (guint16) 1);
1044     GST_WRITE_UINT16_LE (&bih->bit_cnt, (guint16) 24);
1045     GST_WRITE_UINT32_LE (&bih->image_size, videocontext->pixel_width *
1046         videocontext->pixel_height * 3);
1047
1048     /* process codec private/initialization data, if any */
1049     if (codec_buf) {
1050       size += gst_buffer_get_size (codec_buf);
1051       bih = g_realloc (bih, size);
1052       GST_WRITE_UINT32_LE (&bih->size, size);
1053       gst_buffer_extract (codec_buf, 0,
1054           (guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
1055     }
1056
1057     gst_matroska_mux_set_codec_id (context,
1058         GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
1059     gst_matroska_mux_free_codec_priv (context);
1060     context->codec_priv = (gpointer) bih;
1061     context->codec_priv_size = size;
1062   } else if (!strcmp (mimetype, "video/x-h264")) {
1063     gst_matroska_mux_set_codec_id (context,
1064         GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC);
1065     gst_matroska_mux_free_codec_priv (context);
1066     /* Create avcC header */
1067     if (codec_buf != NULL) {
1068       context->codec_priv_size = gst_buffer_get_size (codec_buf);
1069       context->codec_priv = g_malloc0 (context->codec_priv_size);
1070       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
1071     }
1072   } else if (!strcmp (mimetype, "video/x-theora")) {
1073     const GValue *streamheader;
1074
1075     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_THEORA);
1076
1077     gst_matroska_mux_free_codec_priv (context);
1078
1079     streamheader = gst_structure_get_value (structure, "streamheader");
1080     if (!theora_streamheader_to_codecdata (streamheader, context)) {
1081       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1082           ("theora stream headers missing or malformed"));
1083       goto refuse_caps;
1084     }
1085   } else if (!strcmp (mimetype, "video/x-dirac")) {
1086     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_DIRAC);
1087   } else if (!strcmp (mimetype, "video/x-vp8")) {
1088     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_VP8);
1089   } else if (!strcmp (mimetype, "video/mpeg")) {
1090     gint mpegversion;
1091
1092     gst_structure_get_int (structure, "mpegversion", &mpegversion);
1093     switch (mpegversion) {
1094       case 1:
1095         gst_matroska_mux_set_codec_id (context,
1096             GST_MATROSKA_CODEC_ID_VIDEO_MPEG1);
1097         break;
1098       case 2:
1099         gst_matroska_mux_set_codec_id (context,
1100             GST_MATROSKA_CODEC_ID_VIDEO_MPEG2);
1101         break;
1102       case 4:
1103         gst_matroska_mux_set_codec_id (context,
1104             GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP);
1105         break;
1106       default:
1107         goto refuse_caps;
1108     }
1109
1110     /* global headers may be in codec data */
1111     if (codec_buf != NULL) {
1112       gst_matroska_mux_free_codec_priv (context);
1113       context->codec_priv_size = gst_buffer_get_size (codec_buf);
1114       context->codec_priv = g_malloc0 (context->codec_priv_size);
1115       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
1116     }
1117   } else if (!strcmp (mimetype, "video/x-msmpeg")) {
1118   msmpeg43:
1119     /* can only make it here if preceding case verified it was version 3 */
1120     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3);
1121   } else if (!strcmp (mimetype, "video/x-pn-realvideo")) {
1122     gint rmversion;
1123     const GValue *mdpr_data;
1124
1125     gst_structure_get_int (structure, "rmversion", &rmversion);
1126     switch (rmversion) {
1127       case 1:
1128         gst_matroska_mux_set_codec_id (context,
1129             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
1130         break;
1131       case 2:
1132         gst_matroska_mux_set_codec_id (context,
1133             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
1134         break;
1135       case 3:
1136         gst_matroska_mux_set_codec_id (context,
1137             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
1138         break;
1139       case 4:
1140         gst_matroska_mux_set_codec_id (context,
1141             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
1142         break;
1143       default:
1144         goto refuse_caps;
1145     }
1146
1147     mdpr_data = gst_structure_get_value (structure, "mdpr_data");
1148     if (mdpr_data != NULL) {
1149       guint8 *priv_data = NULL;
1150       guint priv_data_size = 0;
1151
1152       GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
1153
1154       priv_data_size = gst_buffer_get_size (codec_data_buf);
1155       priv_data = g_malloc0 (priv_data_size);
1156
1157       gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
1158
1159       gst_matroska_mux_free_codec_priv (context);
1160       context->codec_priv = priv_data;
1161       context->codec_priv_size = priv_data_size;
1162     }
1163   }
1164
1165   return TRUE;
1166
1167   /* ERRORS */
1168 refuse_caps:
1169   {
1170     GST_WARNING_OBJECT (mux, "pad %s refused caps %" GST_PTR_FORMAT,
1171         GST_PAD_NAME (pad), caps);
1172     return FALSE;
1173   }
1174 }
1175
1176 /* N > 0 to expect a particular number of headers, negative if the
1177    number of headers is variable */
1178 static gboolean
1179 xiphN_streamheader_to_codecdata (const GValue * streamheader,
1180     GstMatroskaTrackContext * context, GstBuffer ** p_buf0, int N)
1181 {
1182   GstBuffer **buf = NULL;
1183   GArray *bufarr;
1184   guint8 *priv_data;
1185   guint bufi, i, offset, priv_data_size;
1186
1187   if (streamheader == NULL)
1188     goto no_stream_headers;
1189
1190   if (G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY)
1191     goto wrong_type;
1192
1193   bufarr = g_value_peek_pointer (streamheader);
1194   if (bufarr->len <= 0 || bufarr->len > 255)    /* at least one header, and count stored in a byte */
1195     goto wrong_count;
1196   if (N > 0 && bufarr->len != N)
1197     goto wrong_count;
1198
1199   context->xiph_headers_to_skip = bufarr->len;
1200
1201   buf = (GstBuffer **) g_malloc0 (sizeof (GstBuffer *) * bufarr->len);
1202   for (i = 0; i < bufarr->len; i++) {
1203     GValue *bufval = &g_array_index (bufarr, GValue, i);
1204
1205     if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1206       g_free (buf);
1207       goto wrong_content_type;
1208     }
1209
1210     buf[i] = g_value_peek_pointer (bufval);
1211   }
1212
1213   priv_data_size = 1;
1214   if (bufarr->len > 0) {
1215     for (i = 0; i < bufarr->len - 1; i++) {
1216       priv_data_size += gst_buffer_get_size (buf[i]) / 0xff + 1;
1217     }
1218   }
1219
1220   for (i = 0; i < bufarr->len; ++i) {
1221     priv_data_size += gst_buffer_get_size (buf[i]);
1222   }
1223
1224   priv_data = g_malloc0 (priv_data_size);
1225
1226   priv_data[0] = bufarr->len - 1;
1227   offset = 1;
1228
1229   if (bufarr->len > 0) {
1230     for (bufi = 0; bufi < bufarr->len - 1; bufi++) {
1231       for (i = 0; i < gst_buffer_get_size (buf[bufi]) / 0xff; ++i) {
1232         priv_data[offset++] = 0xff;
1233       }
1234       priv_data[offset++] = gst_buffer_get_size (buf[bufi]) % 0xff;
1235     }
1236   }
1237
1238   for (i = 0; i < bufarr->len; ++i) {
1239     gst_buffer_extract (buf[i], 0, priv_data + offset, -1);
1240     offset += gst_buffer_get_size (buf[i]);
1241   }
1242
1243   gst_matroska_mux_free_codec_priv (context);
1244   context->codec_priv = priv_data;
1245   context->codec_priv_size = priv_data_size;
1246
1247   if (p_buf0)
1248     *p_buf0 = gst_buffer_ref (buf[0]);
1249
1250   g_free (buf);
1251
1252   return TRUE;
1253
1254 /* ERRORS */
1255 no_stream_headers:
1256   {
1257     GST_WARNING ("required streamheaders missing in sink caps!");
1258     return FALSE;
1259   }
1260 wrong_type:
1261   {
1262     GST_WARNING ("streamheaders are not a GST_TYPE_ARRAY, but a %s",
1263         G_VALUE_TYPE_NAME (streamheader));
1264     return FALSE;
1265   }
1266 wrong_count:
1267   {
1268     GST_WARNING ("got %u streamheaders, not %d as expected", bufarr->len, N);
1269     return FALSE;
1270   }
1271 wrong_content_type:
1272   {
1273     GST_WARNING ("streamheaders array does not contain GstBuffers");
1274     return FALSE;
1275   }
1276 }
1277
1278 static gboolean
1279 vorbis_streamheader_to_codecdata (const GValue * streamheader,
1280     GstMatroskaTrackContext * context)
1281 {
1282   GstBuffer *buf0 = NULL;
1283
1284   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
1285     return FALSE;
1286
1287   if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 4) {
1288     GST_WARNING ("First vorbis header too small, ignoring");
1289   } else {
1290     if (gst_buffer_memcmp (buf0, 1, "vorbis", 6) == 0) {
1291       GstMatroskaTrackAudioContext *audiocontext;
1292       GstMapInfo map;
1293       guint8 *hdr;
1294
1295       gst_buffer_map (buf0, &map, GST_MAP_READ);
1296       hdr = map.data + 1 + 6 + 4;
1297       audiocontext = (GstMatroskaTrackAudioContext *) context;
1298       audiocontext->channels = GST_READ_UINT8 (hdr);
1299       audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1);
1300       gst_buffer_unmap (buf0, &map);
1301     }
1302   }
1303
1304   if (buf0)
1305     gst_buffer_unref (buf0);
1306
1307   return TRUE;
1308 }
1309
1310 static gboolean
1311 theora_streamheader_to_codecdata (const GValue * streamheader,
1312     GstMatroskaTrackContext * context)
1313 {
1314   GstBuffer *buf0 = NULL;
1315
1316   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
1317     return FALSE;
1318
1319   if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 26) {
1320     GST_WARNING ("First theora header too small, ignoring");
1321   } else if (gst_buffer_memcmp (buf0, 0, "\200theora\003\002", 9) != 0) {
1322     GST_WARNING ("First header not a theora identification header, ignoring");
1323   } else {
1324     GstMatroskaTrackVideoContext *videocontext;
1325     guint fps_num, fps_denom, par_num, par_denom;
1326     GstMapInfo map;
1327     guint8 *hdr;
1328
1329     gst_buffer_map (buf0, &map, GST_MAP_READ);
1330     hdr = map.data + 1 + 6 + 3 + 2 + 2;
1331
1332     videocontext = (GstMatroskaTrackVideoContext *) context;
1333     videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8;
1334     videocontext->pixel_height = GST_READ_UINT32_BE (hdr + 3) >> 8;
1335     hdr += 3 + 3 + 1 + 1;
1336     fps_num = GST_READ_UINT32_BE (hdr);
1337     fps_denom = GST_READ_UINT32_BE (hdr + 4);
1338     context->default_duration = gst_util_uint64_scale_int (GST_SECOND,
1339         fps_denom, fps_num);
1340     hdr += 4 + 4;
1341     par_num = GST_READ_UINT32_BE (hdr) >> 8;
1342     par_denom = GST_READ_UINT32_BE (hdr + 3) >> 8;
1343     if (par_num > 0 && par_num > 0) {
1344       if (par_num > par_denom) {
1345         videocontext->display_width =
1346             videocontext->pixel_width * par_num / par_denom;
1347         videocontext->display_height = videocontext->pixel_height;
1348       } else if (par_num < par_denom) {
1349         videocontext->display_width = videocontext->pixel_width;
1350         videocontext->display_height =
1351             videocontext->pixel_height * par_denom / par_num;
1352       } else {
1353         videocontext->display_width = 0;
1354         videocontext->display_height = 0;
1355       }
1356     } else {
1357       videocontext->display_width = 0;
1358       videocontext->display_height = 0;
1359     }
1360     hdr += 3 + 3;
1361
1362     gst_buffer_unmap (buf0, &map);
1363   }
1364
1365   if (buf0)
1366     gst_buffer_unref (buf0);
1367
1368   return TRUE;
1369 }
1370
1371 static gboolean
1372 kate_streamheader_to_codecdata (const GValue * streamheader,
1373     GstMatroskaTrackContext * context)
1374 {
1375   GstBuffer *buf0 = NULL;
1376
1377   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1))
1378     return FALSE;
1379
1380   if (buf0 == NULL || gst_buffer_get_size (buf0) < 64) {        /* Kate ID header is 64 bytes */
1381     GST_WARNING ("First kate header too small, ignoring");
1382   } else if (gst_buffer_memcmp (buf0, 0, "\200kate\0\0\0", 8) != 0) {
1383     GST_WARNING ("First header not a kate identification header, ignoring");
1384   }
1385
1386   if (buf0)
1387     gst_buffer_unref (buf0);
1388
1389   return TRUE;
1390 }
1391
1392 static gboolean
1393 flac_streamheader_to_codecdata (const GValue * streamheader,
1394     GstMatroskaTrackContext * context)
1395 {
1396   GArray *bufarr;
1397   gint i;
1398   GValue *bufval;
1399   GstBuffer *buffer;
1400
1401   if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
1402     GST_WARNING ("No or invalid streamheader field in the caps");
1403     return FALSE;
1404   }
1405
1406   bufarr = g_value_peek_pointer (streamheader);
1407   if (bufarr->len < 2) {
1408     GST_WARNING ("Too few headers in streamheader field");
1409     return FALSE;
1410   }
1411
1412   context->xiph_headers_to_skip = bufarr->len + 1;
1413
1414   bufval = &g_array_index (bufarr, GValue, 0);
1415   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1416     GST_WARNING ("streamheaders array does not contain GstBuffers");
1417     return FALSE;
1418   }
1419
1420   buffer = g_value_peek_pointer (bufval);
1421
1422   /* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */
1423   if (gst_buffer_get_size (buffer) < 9 + 4 + 4 + 34
1424       || gst_buffer_memcmp (buffer, 1, "FLAC", 4) != 0
1425       || gst_buffer_memcmp (buffer, 9, "fLaC", 4) != 0) {
1426     GST_WARNING ("Invalid streamheader for FLAC");
1427     return FALSE;
1428   }
1429
1430   gst_matroska_mux_free_codec_priv (context);
1431   context->codec_priv_size = gst_buffer_get_size (buffer) - 9;
1432   context->codec_priv = g_malloc (context->codec_priv_size);
1433   gst_buffer_extract (buffer, 9, context->codec_priv, -1);
1434
1435   for (i = 1; i < bufarr->len; i++) {
1436     guint old_size;
1437     bufval = &g_array_index (bufarr, GValue, i);
1438
1439     if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1440       gst_matroska_mux_free_codec_priv (context);
1441       GST_WARNING ("streamheaders array does not contain GstBuffers");
1442       return FALSE;
1443     }
1444
1445     buffer = g_value_peek_pointer (bufval);
1446
1447     old_size = context->codec_priv_size;
1448     context->codec_priv_size += gst_buffer_get_size (buffer);
1449
1450     context->codec_priv = g_realloc (context->codec_priv,
1451         context->codec_priv_size);
1452     gst_buffer_extract (buffer, 0,
1453         (guint8 *) context->codec_priv + old_size, -1);
1454   }
1455
1456   return TRUE;
1457 }
1458
1459 static gboolean
1460 speex_streamheader_to_codecdata (const GValue * streamheader,
1461     GstMatroskaTrackContext * context)
1462 {
1463   GArray *bufarr;
1464   GValue *bufval;
1465   GstBuffer *buffer;
1466   guint old_size;
1467
1468   if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
1469     GST_WARNING ("No or invalid streamheader field in the caps");
1470     return FALSE;
1471   }
1472
1473   bufarr = g_value_peek_pointer (streamheader);
1474   if (bufarr->len != 2) {
1475     GST_WARNING ("Too few headers in streamheader field");
1476     return FALSE;
1477   }
1478
1479   context->xiph_headers_to_skip = bufarr->len + 1;
1480
1481   bufval = &g_array_index (bufarr, GValue, 0);
1482   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1483     GST_WARNING ("streamheaders array does not contain GstBuffers");
1484     return FALSE;
1485   }
1486
1487   buffer = g_value_peek_pointer (bufval);
1488
1489   if (gst_buffer_get_size (buffer) < 80
1490       || gst_buffer_memcmp (buffer, 0, "Speex   ", 8) != 0) {
1491     GST_WARNING ("Invalid streamheader for Speex");
1492     return FALSE;
1493   }
1494
1495   gst_matroska_mux_free_codec_priv (context);
1496   context->codec_priv_size = gst_buffer_get_size (buffer);
1497   context->codec_priv = g_malloc (context->codec_priv_size);
1498   gst_buffer_extract (buffer, 0, context->codec_priv, -1);
1499
1500   bufval = &g_array_index (bufarr, GValue, 1);
1501
1502   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1503     gst_matroska_mux_free_codec_priv (context);
1504     GST_WARNING ("streamheaders array does not contain GstBuffers");
1505     return FALSE;
1506   }
1507
1508   buffer = g_value_peek_pointer (bufval);
1509
1510   old_size = context->codec_priv_size;
1511   context->codec_priv_size += gst_buffer_get_size (buffer);
1512   context->codec_priv = g_realloc (context->codec_priv,
1513       context->codec_priv_size);
1514   gst_buffer_extract (buffer, 0, (guint8 *) context->codec_priv + old_size, -1);
1515
1516   return TRUE;
1517 }
1518
1519 static const gchar *
1520 aac_codec_data_to_codec_id (GstBuffer * buf)
1521 {
1522   const gchar *result;
1523   guint8 profile;
1524
1525   /* default to MAIN */
1526   profile = 1;
1527
1528   if (gst_buffer_get_size (buf) >= 2) {
1529     gst_buffer_extract (buf, 0, &profile, 1);
1530     profile >>= 3;
1531   }
1532
1533   switch (profile) {
1534     case 1:
1535       result = "MAIN";
1536       break;
1537     case 2:
1538       result = "LC";
1539       break;
1540     case 3:
1541       result = "SSR";
1542       break;
1543     case 4:
1544       result = "LTP";
1545       break;
1546     default:
1547       GST_WARNING ("unknown AAC profile, defaulting to MAIN");
1548       result = "MAIN";
1549       break;
1550   }
1551
1552   return result;
1553 }
1554
1555 /**
1556  * gst_matroska_mux_audio_pad_setcaps:
1557  * @pad: Pad which got the caps.
1558  * @caps: New caps.
1559  *
1560  * Setcaps function for audio sink pad.
1561  *
1562  * Returns: #TRUE on success.
1563  */
1564 static gboolean
1565 gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
1566 {
1567   GstMatroskaTrackContext *context = NULL;
1568   GstMatroskaTrackAudioContext *audiocontext;
1569   GstMatroskaMux *mux;
1570   GstMatroskaPad *collect_pad;
1571   const gchar *mimetype;
1572   gint samplerate = 0, channels = 0;
1573   GstStructure *structure;
1574   const GValue *codec_data = NULL;
1575   GstBuffer *buf = NULL;
1576   const gchar *stream_format = NULL;
1577
1578   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
1579
1580   /* find context */
1581   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
1582   g_assert (collect_pad);
1583   context = collect_pad->track;
1584   g_assert (context);
1585   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO);
1586   audiocontext = (GstMatroskaTrackAudioContext *) context;
1587
1588   structure = gst_caps_get_structure (caps, 0);
1589   mimetype = gst_structure_get_name (structure);
1590
1591   /* general setup */
1592   gst_structure_get_int (structure, "rate", &samplerate);
1593   gst_structure_get_int (structure, "channels", &channels);
1594
1595   audiocontext->samplerate = samplerate;
1596   audiocontext->channels = channels;
1597   audiocontext->bitdepth = 0;
1598   context->default_duration = 0;
1599
1600   codec_data = gst_structure_get_value (structure, "codec_data");
1601   if (codec_data)
1602     buf = gst_value_get_buffer (codec_data);
1603
1604   /* TODO: - check if we handle all codecs by the spec, i.e. codec private
1605    *         data and other settings
1606    *       - add new formats
1607    */
1608
1609   if (!strcmp (mimetype, "audio/mpeg")) {
1610     gint mpegversion = 0;
1611
1612     gst_structure_get_int (structure, "mpegversion", &mpegversion);
1613     switch (mpegversion) {
1614       case 1:{
1615         gint layer;
1616         gint version = 1;
1617         gint spf;
1618
1619         gst_structure_get_int (structure, "layer", &layer);
1620
1621         if (!gst_structure_get_int (structure, "mpegaudioversion", &version)) {
1622           GST_WARNING_OBJECT (mux,
1623               "Unable to determine MPEG audio version, assuming 1");
1624           version = 1;
1625         }
1626
1627         if (layer == 1)
1628           spf = 384;
1629         else if (layer == 2)
1630           spf = 1152;
1631         else if (version == 2)
1632           spf = 576;
1633         else
1634           spf = 1152;
1635
1636         context->default_duration =
1637             gst_util_uint64_scale (GST_SECOND, spf, audiocontext->samplerate);
1638
1639         switch (layer) {
1640           case 1:
1641             gst_matroska_mux_set_codec_id (context,
1642                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1);
1643             break;
1644           case 2:
1645             gst_matroska_mux_set_codec_id (context,
1646                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2);
1647             break;
1648           case 3:
1649             gst_matroska_mux_set_codec_id (context,
1650                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3);
1651             break;
1652           default:
1653             goto refuse_caps;
1654         }
1655         break;
1656       }
1657       case 2:
1658       case 4:
1659         stream_format = gst_structure_get_string (structure, "stream-format");
1660         /* check this is raw aac */
1661         if (stream_format) {
1662           if (strcmp (stream_format, "raw") != 0) {
1663             GST_WARNING_OBJECT (mux, "AAC stream-format must be 'raw', not %s",
1664                 stream_format);
1665           }
1666         } else {
1667           GST_WARNING_OBJECT (mux, "AAC stream-format not specified, "
1668               "assuming 'raw'");
1669         }
1670
1671         if (buf) {
1672           if (mpegversion == 2)
1673             context->codec_id =
1674                 g_strdup_printf (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2 "%s",
1675                 aac_codec_data_to_codec_id (buf));
1676           else if (mpegversion == 4)
1677             context->codec_id =
1678                 g_strdup_printf (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4 "%s",
1679                 aac_codec_data_to_codec_id (buf));
1680           else
1681             g_assert_not_reached ();
1682         } else {
1683           GST_DEBUG_OBJECT (mux, "no AAC codec_data; not packetized");
1684           goto refuse_caps;
1685         }
1686         break;
1687       default:
1688         goto refuse_caps;
1689     }
1690   } else if (!strcmp (mimetype, "audio/x-raw")) {
1691     GstAudioInfo info;
1692
1693     gst_audio_info_init (&info);
1694     if (!gst_audio_info_from_caps (&info, caps)) {
1695       GST_DEBUG_OBJECT (mux,
1696           "broken caps, rejected by gst_audio_info_from_caps");
1697       goto refuse_caps;
1698     }
1699
1700     switch (GST_AUDIO_INFO_FORMAT (&info)) {
1701       case GST_AUDIO_FORMAT_U8:
1702       case GST_AUDIO_FORMAT_S16BE:
1703       case GST_AUDIO_FORMAT_S16LE:
1704       case GST_AUDIO_FORMAT_S24BE:
1705       case GST_AUDIO_FORMAT_S24LE:
1706       case GST_AUDIO_FORMAT_S32BE:
1707       case GST_AUDIO_FORMAT_S32LE:
1708         if (GST_AUDIO_INFO_WIDTH (&info) != GST_AUDIO_INFO_DEPTH (&info)) {
1709           GST_DEBUG_OBJECT (mux, "width must be same as depth!");
1710           goto refuse_caps;
1711         }
1712         if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info))
1713           gst_matroska_mux_set_codec_id (context,
1714               GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
1715         else
1716           gst_matroska_mux_set_codec_id (context,
1717               GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
1718         break;
1719       case GST_AUDIO_FORMAT_F32LE:
1720       case GST_AUDIO_FORMAT_F64LE:
1721         gst_matroska_mux_set_codec_id (context,
1722             GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
1723         break;
1724
1725       default:
1726         GST_DEBUG_OBJECT (mux, "wrong format in raw audio caps");
1727         goto refuse_caps;
1728     }
1729
1730     audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
1731   } else if (!strcmp (mimetype, "audio/x-vorbis")) {
1732     const GValue *streamheader;
1733
1734     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS);
1735
1736     gst_matroska_mux_free_codec_priv (context);
1737
1738     streamheader = gst_structure_get_value (structure, "streamheader");
1739     if (!vorbis_streamheader_to_codecdata (streamheader, context)) {
1740       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1741           ("vorbis stream headers missing or malformed"));
1742       goto refuse_caps;
1743     }
1744   } else if (!strcmp (mimetype, "audio/x-flac")) {
1745     const GValue *streamheader;
1746
1747     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_FLAC);
1748
1749     gst_matroska_mux_free_codec_priv (context);
1750
1751     streamheader = gst_structure_get_value (structure, "streamheader");
1752     if (!flac_streamheader_to_codecdata (streamheader, context)) {
1753       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1754           ("flac stream headers missing or malformed"));
1755       goto refuse_caps;
1756     }
1757   } else if (!strcmp (mimetype, "audio/x-speex")) {
1758     const GValue *streamheader;
1759
1760     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_SPEEX);
1761     gst_matroska_mux_free_codec_priv (context);
1762
1763     streamheader = gst_structure_get_value (structure, "streamheader");
1764     if (!speex_streamheader_to_codecdata (streamheader, context)) {
1765       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1766           ("speex stream headers missing or malformed"));
1767       goto refuse_caps;
1768     }
1769   } else if (!strcmp (mimetype, "audio/x-ac3")) {
1770     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_AC3);
1771   } else if (!strcmp (mimetype, "audio/x-eac3")) {
1772     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_EAC3);
1773   } else if (!strcmp (mimetype, "audio/x-dts")) {
1774     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_DTS);
1775   } else if (!strcmp (mimetype, "audio/x-tta")) {
1776     gint width;
1777
1778     /* TTA frame duration */
1779     context->default_duration = 1.04489795918367346939 * GST_SECOND;
1780
1781     gst_structure_get_int (structure, "width", &width);
1782     audiocontext->bitdepth = width;
1783     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_TTA);
1784
1785   } else if (!strcmp (mimetype, "audio/x-pn-realaudio")) {
1786     gint raversion;
1787     const GValue *mdpr_data;
1788
1789     gst_structure_get_int (structure, "raversion", &raversion);
1790     switch (raversion) {
1791       case 1:
1792         gst_matroska_mux_set_codec_id (context,
1793             GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
1794         break;
1795       case 2:
1796         gst_matroska_mux_set_codec_id (context,
1797             GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
1798         break;
1799       case 8:
1800         gst_matroska_mux_set_codec_id (context,
1801             GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
1802         break;
1803       default:
1804         goto refuse_caps;
1805     }
1806
1807     mdpr_data = gst_structure_get_value (structure, "mdpr_data");
1808     if (mdpr_data != NULL) {
1809       guint8 *priv_data = NULL;
1810       guint priv_data_size = 0;
1811
1812       GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
1813
1814       priv_data_size = gst_buffer_get_size (codec_data_buf);
1815       priv_data = g_malloc0 (priv_data_size);
1816
1817       gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
1818
1819       gst_matroska_mux_free_codec_priv (context);
1820
1821       context->codec_priv = priv_data;
1822       context->codec_priv_size = priv_data_size;
1823     }
1824
1825   } else if (!strcmp (mimetype, "audio/x-wma")
1826       || !strcmp (mimetype, "audio/x-alaw")
1827       || !strcmp (mimetype, "audio/x-mulaw")) {
1828     guint8 *codec_priv;
1829     guint codec_priv_size;
1830     guint16 format = 0;
1831     gint block_align;
1832     gint bitrate;
1833
1834     if (samplerate == 0 || channels == 0) {
1835       GST_WARNING_OBJECT (mux, "Missing channels/samplerate on caps");
1836       goto refuse_caps;
1837     }
1838
1839     if (!strcmp (mimetype, "audio/x-wma")) {
1840       gint wmaversion;
1841       gint depth;
1842
1843       if (!gst_structure_get_int (structure, "wmaversion", &wmaversion)
1844           || !gst_structure_get_int (structure, "block_align", &block_align)
1845           || !gst_structure_get_int (structure, "bitrate", &bitrate)) {
1846         GST_WARNING_OBJECT (mux, "Missing wmaversion/block_align/bitrate"
1847             " on WMA caps");
1848         goto refuse_caps;
1849       }
1850
1851       switch (wmaversion) {
1852         case 1:
1853           format = GST_RIFF_WAVE_FORMAT_WMAV1;
1854           break;
1855         case 2:
1856           format = GST_RIFF_WAVE_FORMAT_WMAV2;
1857           break;
1858         case 3:
1859           format = GST_RIFF_WAVE_FORMAT_WMAV3;
1860           break;
1861         default:
1862           GST_WARNING_OBJECT (mux, "Unexpected WMA version: %d", wmaversion);
1863           goto refuse_caps;
1864       }
1865
1866       if (gst_structure_get_int (structure, "depth", &depth))
1867         audiocontext->bitdepth = depth;
1868     } else if (!strcmp (mimetype, "audio/x-alaw")
1869         || !strcmp (mimetype, "audio/x-mulaw")) {
1870       audiocontext->bitdepth = 8;
1871       if (!strcmp (mimetype, "audio/x-alaw"))
1872         format = GST_RIFF_WAVE_FORMAT_ALAW;
1873       else
1874         format = GST_RIFF_WAVE_FORMAT_MULAW;
1875
1876       block_align = channels;
1877       bitrate = block_align * samplerate;
1878     }
1879     g_assert (format != 0);
1880
1881     codec_priv_size = WAVEFORMATEX_SIZE;
1882     if (buf)
1883       codec_priv_size += gst_buffer_get_size (buf);
1884
1885     /* serialize waveformatex structure */
1886     codec_priv = g_malloc0 (codec_priv_size);
1887     GST_WRITE_UINT16_LE (codec_priv, format);
1888     GST_WRITE_UINT16_LE (codec_priv + 2, channels);
1889     GST_WRITE_UINT32_LE (codec_priv + 4, samplerate);
1890     GST_WRITE_UINT32_LE (codec_priv + 8, bitrate / 8);
1891     GST_WRITE_UINT16_LE (codec_priv + 12, block_align);
1892     GST_WRITE_UINT16_LE (codec_priv + 14, 0);
1893     if (buf)
1894       GST_WRITE_UINT16_LE (codec_priv + 16, gst_buffer_get_size (buf));
1895     else
1896       GST_WRITE_UINT16_LE (codec_priv + 16, 0);
1897
1898     /* process codec private/initialization data, if any */
1899     if (buf) {
1900       gst_buffer_extract (buf, 0,
1901           (guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
1902     }
1903
1904     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_ACM);
1905     gst_matroska_mux_free_codec_priv (context);
1906     context->codec_priv = (gpointer) codec_priv;
1907     context->codec_priv_size = codec_priv_size;
1908   }
1909
1910   return TRUE;
1911
1912   /* ERRORS */
1913 refuse_caps:
1914   {
1915     GST_WARNING_OBJECT (mux, "pad %s refused caps %" GST_PTR_FORMAT,
1916         GST_PAD_NAME (pad), caps);
1917     return FALSE;
1918   }
1919 }
1920
1921 /* we probably don't have the data at start,
1922  * so have to reserve (a maximum) space to write this at the end.
1923  * bit spacy, but some formats can hold quite some */
1924 #define SUBTITLE_MAX_CODEC_PRIVATE   2048       /* must be > 128 */
1925
1926 /**
1927  * gst_matroska_mux_subtitle_pad_setcaps:
1928  * @pad: Pad which got the caps.
1929  * @caps: New caps.
1930  *
1931  * Setcaps function for subtitle sink pad.
1932  *
1933  * Returns: #TRUE on success.
1934  */
1935 static gboolean
1936 gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
1937 {
1938   /* There is now (at least) one such alement (kateenc), and I'm going
1939      to handle it here and claim it works when it can be piped back
1940      through GStreamer and VLC */
1941
1942   GstMatroskaTrackContext *context = NULL;
1943   GstMatroskaTrackSubtitleContext *scontext;
1944   GstMatroskaMux *mux;
1945   GstMatroskaPad *collect_pad;
1946   const gchar *mimetype;
1947   GstStructure *structure;
1948   const GValue *value = NULL;
1949   GstBuffer *buf = NULL;
1950   gchar *id = NULL;
1951   gboolean ret = TRUE;
1952
1953   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
1954
1955   /* find context */
1956   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
1957   g_assert (collect_pad);
1958   context = collect_pad->track;
1959   g_assert (context);
1960   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE);
1961   scontext = (GstMatroskaTrackSubtitleContext *) context;
1962
1963   structure = gst_caps_get_structure (caps, 0);
1964   mimetype = gst_structure_get_name (structure);
1965
1966   /* keep track of default set in request_pad */
1967   id = context->codec_id;
1968
1969   /* general setup */
1970   scontext->check_utf8 = 1;
1971   scontext->invalid_utf8 = 0;
1972   context->default_duration = 0;
1973
1974   if (!strcmp (mimetype, "subtitle/x-kate")) {
1975     const GValue *streamheader;
1976
1977     gst_matroska_mux_set_codec_id (context,
1978         GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
1979
1980     gst_matroska_mux_free_codec_priv (context);
1981
1982     streamheader = gst_structure_get_value (structure, "streamheader");
1983     if (!kate_streamheader_to_codecdata (streamheader, context)) {
1984       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1985           ("kate stream headers missing or malformed"));
1986       ret = FALSE;
1987       goto exit;
1988     }
1989   } else if (!strcmp (mimetype, "text/plain")) {
1990     gst_matroska_mux_set_codec_id (context,
1991         GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8);
1992   } else if (!strcmp (mimetype, "application/x-ssa")) {
1993     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_SSA);
1994   } else if (!strcmp (mimetype, "application/x-ass")) {
1995     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_ASS);
1996   } else if (!strcmp (mimetype, "application/x-usf")) {
1997     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_USF);
1998   } else if (!strcmp (mimetype, "video/x-dvd-subpicture")) {
1999     gst_matroska_mux_set_codec_id (context,
2000         GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB);
2001   } else {
2002     id = NULL;
2003     ret = FALSE;
2004     goto exit;
2005   }
2006
2007   /* maybe some private data, e.g. vobsub */
2008   value = gst_structure_get_value (structure, "codec_data");
2009   if (value)
2010     buf = gst_value_get_buffer (value);
2011   if (buf != NULL) {
2012     GstMapInfo map;
2013     guint8 *priv_data = NULL;
2014
2015     gst_buffer_map (buf, &map, GST_MAP_READ);
2016
2017     if (map.size > SUBTITLE_MAX_CODEC_PRIVATE) {
2018       GST_WARNING_OBJECT (mux, "pad %" GST_PTR_FORMAT " subtitle private data"
2019           " exceeded maximum (%d); discarding", pad,
2020           SUBTITLE_MAX_CODEC_PRIVATE);
2021       gst_buffer_unmap (buf, &map);
2022       return TRUE;
2023     }
2024
2025     gst_matroska_mux_free_codec_priv (context);
2026
2027     priv_data = g_malloc0 (map.size);
2028     memcpy (priv_data, map.data, map.size);
2029     context->codec_priv = priv_data;
2030     context->codec_priv_size = map.size;
2031     gst_buffer_unmap (buf, &map);
2032   }
2033
2034   GST_DEBUG_OBJECT (pad, "codec_id %s, codec data size %" G_GSIZE_FORMAT,
2035       GST_STR_NULL (context->codec_id), context->codec_priv_size);
2036
2037 exit:
2038   /* free default if modified */
2039   if (id)
2040     g_free (id);
2041
2042   return ret;
2043 }
2044
2045
2046 /**
2047  * gst_matroska_mux_request_new_pad:
2048  * @element: #GstMatroskaMux.
2049  * @templ: #GstPadTemplate.
2050  * @pad_name: New pad name.
2051  *
2052  * Request pad function for sink templates.
2053  *
2054  * Returns: New #GstPad.
2055  */
2056 static GstPad *
2057 gst_matroska_mux_request_new_pad (GstElement * element,
2058     GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
2059 {
2060   GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
2061   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
2062   GstMatroskaPad *collect_pad;
2063   GstMatroskamuxPad *newpad;
2064   gchar *name = NULL;
2065   const gchar *pad_name = NULL;
2066   GstMatroskaCapsFunc capsfunc = NULL;
2067   GstMatroskaTrackContext *context = NULL;
2068   gint pad_id;
2069   gboolean locked = TRUE;
2070   gchar *id = NULL;
2071
2072   if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
2073     /* don't mix named and unnamed pads, if the pad already exists we fail when
2074      * trying to add it */
2075     if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
2076       pad_name = req_name;
2077     } else {
2078       name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
2079       pad_name = name;
2080     }
2081     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
2082     context = (GstMatroskaTrackContext *)
2083         g_new0 (GstMatroskaTrackAudioContext, 1);
2084     context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
2085     context->name = g_strdup ("Audio");
2086   } else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
2087     /* don't mix named and unnamed pads, if the pad already exists we fail when
2088      * trying to add it */
2089     if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
2090       pad_name = req_name;
2091     } else {
2092       name = g_strdup_printf ("video_%u", mux->num_v_streams++);
2093       pad_name = name;
2094     }
2095     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
2096     context = (GstMatroskaTrackContext *)
2097         g_new0 (GstMatroskaTrackVideoContext, 1);
2098     context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
2099     context->name = g_strdup ("Video");
2100   } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%u")) {
2101     /* don't mix named and unnamed pads, if the pad already exists we fail when
2102      * trying to add it */
2103     if (req_name != NULL && sscanf (req_name, "subtitle_%u", &pad_id) == 1) {
2104       pad_name = req_name;
2105     } else {
2106       name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++);
2107       pad_name = name;
2108     }
2109     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
2110     context = (GstMatroskaTrackContext *)
2111         g_new0 (GstMatroskaTrackSubtitleContext, 1);
2112     context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
2113     context->name = g_strdup ("Subtitle");
2114     /* setcaps may only provide proper one a lot later */
2115     id = g_strdup ("S_SUB_UNKNOWN");
2116     locked = FALSE;
2117   } else {
2118     GST_WARNING_OBJECT (mux, "This is not our template!");
2119     return NULL;
2120   }
2121
2122   newpad = g_object_new (GST_TYPE_MATROSKAMUX_PAD,
2123       "name", pad_name, "direction", templ->direction, "template", templ, NULL);
2124   g_free (name);
2125
2126   gst_matroskamux_pad_init (newpad);
2127   collect_pad = (GstMatroskaPad *)
2128       gst_collect_pads2_add_pad_full (mux->collect, GST_PAD (newpad),
2129       sizeof (GstMatroskamuxPad),
2130       (GstCollectData2DestroyNotify) gst_matroska_pad_free, locked);
2131
2132   collect_pad->track = context;
2133   gst_matroska_pad_reset (collect_pad, FALSE);
2134   collect_pad->track->codec_id = id;
2135
2136   collect_pad->capsfunc = capsfunc;
2137   gst_pad_set_active (GST_PAD (newpad), TRUE);
2138   if (!gst_element_add_pad (element, GST_PAD (newpad)))
2139     goto pad_add_failed;
2140
2141   mux->num_streams++;
2142
2143   GST_DEBUG_OBJECT (newpad, "Added new request pad");
2144
2145   return GST_PAD (newpad);
2146
2147   /* ERROR cases */
2148 pad_add_failed:
2149   {
2150     GST_WARNING_OBJECT (mux, "Adding the new pad '%s' failed", pad_name);
2151     gst_object_unref (newpad);
2152     return NULL;
2153   }
2154 }
2155
2156 /**
2157  * gst_matroska_mux_release_pad:
2158  * @element: #GstMatroskaMux.
2159  * @pad: Pad to release.
2160  *
2161  * Release a previously requested pad.
2162 */
2163 static void
2164 gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
2165 {
2166   GstMatroskaMux *mux;
2167   GSList *walk;
2168
2169   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
2170
2171   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
2172     GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
2173     GstMatroskaPad *collect_pad = (GstMatroskaPad *) cdata;
2174
2175     if (cdata->pad == pad) {
2176       GstClockTime min_dur;     /* observed minimum duration */
2177
2178       if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2179           GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2180         min_dur = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2181         if (collect_pad->duration < min_dur)
2182           collect_pad->duration = min_dur;
2183       }
2184
2185       if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
2186           mux->duration < collect_pad->duration)
2187         mux->duration = collect_pad->duration;
2188
2189       break;
2190     }
2191   }
2192
2193   gst_collect_pads2_remove_pad (mux->collect, pad);
2194   if (gst_element_remove_pad (element, pad))
2195     mux->num_streams--;
2196 }
2197
2198
2199 /**
2200  * gst_matroska_mux_track_header:
2201  * @mux: #GstMatroskaMux
2202  * @context: Tack context.
2203  *
2204  * Write a track header.
2205  */
2206 static void
2207 gst_matroska_mux_track_header (GstMatroskaMux * mux,
2208     GstMatroskaTrackContext * context)
2209 {
2210   GstEbmlWrite *ebml = mux->ebml_write;
2211   guint64 master;
2212
2213   /* TODO: check if everything necessary is written and check default values */
2214
2215   /* track type goes before the type-specific stuff */
2216   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKNUMBER, context->num);
2217   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKTYPE, context->type);
2218
2219   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKUID,
2220       gst_matroska_mux_create_uid ());
2221   if (context->default_duration) {
2222     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKDEFAULTDURATION,
2223         context->default_duration);
2224   }
2225   if (context->language) {
2226     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKLANGUAGE,
2227         context->language);
2228   }
2229
2230   /* FIXME: until we have a nice way of getting the codecname
2231    * out of the caps, I'm not going to enable this. Too much
2232    * (useless, double, boring) work... */
2233   /* TODO: Use value from tags if any */
2234   /*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
2235      context->codec_name); */
2236   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
2237
2238   /* type-specific stuff */
2239   switch (context->type) {
2240     case GST_MATROSKA_TRACK_TYPE_VIDEO:{
2241       GstMatroskaTrackVideoContext *videocontext =
2242           (GstMatroskaTrackVideoContext *) context;
2243
2244       master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKVIDEO);
2245       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELWIDTH,
2246           videocontext->pixel_width);
2247       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELHEIGHT,
2248           videocontext->pixel_height);
2249       if (videocontext->display_width && videocontext->display_height) {
2250         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEODISPLAYWIDTH,
2251             videocontext->display_width);
2252         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEODISPLAYHEIGHT,
2253             videocontext->display_height);
2254       }
2255       if (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED)
2256         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOFLAGINTERLACED, 1);
2257       if (videocontext->fourcc) {
2258         guint32 fcc_le = GUINT32_TO_LE (videocontext->fourcc);
2259
2260         gst_ebml_write_binary (ebml, GST_MATROSKA_ID_VIDEOCOLOURSPACE,
2261             (gpointer) & fcc_le, 4);
2262       }
2263       gst_ebml_write_master_finish (ebml, master);
2264
2265       break;
2266     }
2267
2268     case GST_MATROSKA_TRACK_TYPE_AUDIO:{
2269       GstMatroskaTrackAudioContext *audiocontext =
2270           (GstMatroskaTrackAudioContext *) context;
2271
2272       master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKAUDIO);
2273       if (audiocontext->samplerate != 8000)
2274         gst_ebml_write_float (ebml, GST_MATROSKA_ID_AUDIOSAMPLINGFREQ,
2275             audiocontext->samplerate);
2276       if (audiocontext->channels != 1)
2277         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOCHANNELS,
2278             audiocontext->channels);
2279       if (audiocontext->bitdepth) {
2280         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOBITDEPTH,
2281             audiocontext->bitdepth);
2282       }
2283       gst_ebml_write_master_finish (ebml, master);
2284
2285       break;
2286     }
2287
2288       /* this is what we write for now and must be filled
2289        * and remainder void'ed later on */
2290 #define SUBTITLE_DUMMY_SIZE   (1 + 1 + 14 + 1 + 2 + SUBTITLE_MAX_CODEC_PRIVATE)
2291
2292     case GST_MATROSKA_TRACK_TYPE_SUBTITLE:{
2293       gpointer buf;
2294
2295       context->pos = ebml->pos;
2296       /* CodecID is mandatory ... */
2297       gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CODECID, "S_SUB_UNKNOWN");
2298       /* reserve space */
2299       buf = g_malloc0 (SUBTITLE_MAX_CODEC_PRIVATE);
2300       gst_ebml_write_binary (ebml, GST_EBML_ID_VOID, buf,
2301           SUBTITLE_MAX_CODEC_PRIVATE);
2302       g_free (buf);
2303       /* real data has to be written at finish */
2304       return;
2305     }
2306     default:
2307       /* doesn't need type-specific data */
2308       break;
2309   }
2310
2311   gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CODECID, context->codec_id);
2312   if (context->codec_priv)
2313     gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
2314         context->codec_priv, context->codec_priv_size);
2315 }
2316
2317
2318 /**
2319  * gst_matroska_mux_start:
2320  * @mux: #GstMatroskaMux
2321  *
2322  * Start a new matroska file (write headers etc...)
2323  */
2324 static void
2325 gst_matroska_mux_start (GstMatroskaMux * mux)
2326 {
2327   GstEbmlWrite *ebml = mux->ebml_write;
2328   const gchar *doctype;
2329   guint32 seekhead_id[] = { GST_MATROSKA_ID_SEGMENTINFO,
2330     GST_MATROSKA_ID_TRACKS,
2331     GST_MATROSKA_ID_CUES,
2332     GST_MATROSKA_ID_TAGS,
2333     0
2334   };
2335   guint64 master, child;
2336   GSList *collected;
2337   int i;
2338   guint tracknum = 1;
2339   GstClockTime duration = 0;
2340   guint32 segment_uid[4];
2341   GTimeVal time = { 0, 0 };
2342
2343   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
2344     ebml->caps = gst_caps_new_empty_simple ("video/webm");
2345   } else {
2346     ebml->caps = gst_caps_new_empty_simple ("video/x-matroska");
2347   }
2348   /* we start with a EBML header */
2349   doctype = mux->doctype;
2350   GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
2351       doctype, mux->doctype_version);
2352   gst_ebml_write_header (ebml, doctype, mux->doctype_version);
2353
2354   /* the rest of the header is cached */
2355   gst_ebml_write_set_cache (ebml, 0x1000);
2356
2357   /* start a segment */
2358   mux->segment_pos =
2359       gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENT);
2360   mux->segment_master = ebml->pos;
2361
2362   if (!mux->streamable) {
2363     /* seekhead (table of contents) - we set the positions later */
2364     mux->seekhead_pos = ebml->pos;
2365     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKHEAD);
2366     for (i = 0; seekhead_id[i] != 0; i++) {
2367       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKENTRY);
2368       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKID, seekhead_id[i]);
2369       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKPOSITION, -1);
2370       gst_ebml_write_master_finish (ebml, child);
2371     }
2372     gst_ebml_write_master_finish (ebml, master);
2373   }
2374
2375   if (mux->streamable) {
2376     const GstTagList *tags;
2377
2378     /* tags */
2379     tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2380
2381     if (tags != NULL && !gst_tag_list_is_empty (tags)) {
2382       guint64 master_tags, master_tag;
2383
2384       GST_DEBUG_OBJECT (mux, "Writing tags");
2385
2386       /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2387       mux->tags_pos = ebml->pos;
2388       master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2389       master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2390       gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2391       gst_ebml_write_master_finish (ebml, master_tag);
2392       gst_ebml_write_master_finish (ebml, master_tags);
2393     }
2394   }
2395
2396   /* segment info */
2397   mux->info_pos = ebml->pos;
2398   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);
2399   for (i = 0; i < 4; i++) {
2400     segment_uid[i] = g_random_int ();
2401   }
2402   gst_ebml_write_binary (ebml, GST_MATROSKA_ID_SEGMENTUID,
2403       (guint8 *) segment_uid, 16);
2404   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TIMECODESCALE, mux->time_scale);
2405   mux->duration_pos = ebml->pos;
2406   /* get duration */
2407   if (!mux->streamable) {
2408     for (collected = mux->collect->data; collected;
2409         collected = g_slist_next (collected)) {
2410       GstMatroskaPad *collect_pad;
2411       GstPad *thepad;
2412       gint64 trackduration;
2413
2414       collect_pad = (GstMatroskaPad *) collected->data;
2415       thepad = collect_pad->collect.pad;
2416
2417       /* Query the total length of the track. */
2418       GST_DEBUG_OBJECT (thepad, "querying peer duration");
2419       if (gst_pad_peer_query_duration (thepad, GST_FORMAT_TIME, &trackduration)) {
2420         GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
2421             GST_TIME_ARGS (trackduration));
2422         if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
2423           duration = (GstClockTime) trackduration;
2424         }
2425       }
2426     }
2427     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2428         gst_guint64_to_gdouble (duration) /
2429         gst_guint64_to_gdouble (mux->time_scale));
2430   }
2431   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_MUXINGAPP,
2432       "GStreamer plugin version " PACKAGE_VERSION);
2433   if (mux->writing_app && mux->writing_app[0]) {
2434     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, mux->writing_app);
2435   }
2436   g_get_current_time (&time);
2437   gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time.tv_sec);
2438   gst_ebml_write_master_finish (ebml, master);
2439
2440   /* tracks */
2441   mux->tracks_pos = ebml->pos;
2442   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKS);
2443
2444   for (collected = mux->collect->data; collected;
2445       collected = g_slist_next (collected)) {
2446     GstMatroskaPad *collect_pad;
2447     GstPad *thepad;
2448
2449     collect_pad = (GstMatroskaPad *) collected->data;
2450     thepad = collect_pad->collect.pad;
2451
2452     if (gst_pad_is_linked (thepad) && gst_pad_is_active (thepad) &&
2453         collect_pad->track->codec_id != 0) {
2454       collect_pad->track->num = tracknum++;
2455       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
2456       gst_matroska_mux_track_header (mux, collect_pad->track);
2457       gst_ebml_write_master_finish (ebml, child);
2458       /* some remaining pad/track setup */
2459       collect_pad->default_duration_scaled =
2460           gst_util_uint64_scale (collect_pad->track->default_duration,
2461           1, mux->time_scale);
2462     }
2463   }
2464   gst_ebml_write_master_finish (ebml, master);
2465
2466   /* lastly, flush the cache */
2467   gst_ebml_write_flush_cache (ebml, FALSE, 0);
2468 }
2469
2470 static void
2471 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
2472     gpointer data)
2473 {
2474   /* TODO: more sensible tag mappings */
2475   static const struct
2476   {
2477     const gchar *matroska_tagname;
2478     const gchar *gstreamer_tagname;
2479   }
2480   tag_conv[] = {
2481     {
2482     GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2483     GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
2484     GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2485     GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2486     GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2487     GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2488     GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2489     GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2490     GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2491     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2492     GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2493     GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2494     GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2495     GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2496     GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2497   };
2498   GstEbmlWrite *ebml = (GstEbmlWrite *) data;
2499   guint i;
2500   guint64 simpletag_master;
2501
2502   for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
2503     const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2504     const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2505
2506     if (strcmp (tagname_gst, tag) == 0) {
2507       GValue src = { 0, };
2508       gchar *dest;
2509
2510       if (!gst_tag_list_copy_value (&src, list, tag))
2511         break;
2512       if ((dest = gst_value_serialize (&src))) {
2513
2514         simpletag_master = gst_ebml_write_master_start (ebml,
2515             GST_MATROSKA_ID_SIMPLETAG);
2516         gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_TAGNAME, tagname_mkv);
2517         gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TAGSTRING, dest);
2518         gst_ebml_write_master_finish (ebml, simpletag_master);
2519         g_free (dest);
2520       } else {
2521         GST_WARNING ("Can't transform tag '%s' to string", tagname_mkv);
2522       }
2523       g_value_unset (&src);
2524       break;
2525     }
2526   }
2527 }
2528
2529
2530 /**
2531  * gst_matroska_mux_finish:
2532  * @mux: #GstMatroskaMux
2533  *
2534  * Finish a new matroska file (write index etc...)
2535  */
2536 static void
2537 gst_matroska_mux_finish (GstMatroskaMux * mux)
2538 {
2539   GstEbmlWrite *ebml = mux->ebml_write;
2540   guint64 pos;
2541   guint64 duration = 0;
2542   GSList *collected;
2543   const GstTagList *tags;
2544
2545   /* finish last cluster */
2546   if (mux->cluster) {
2547     gst_ebml_write_master_finish (ebml, mux->cluster);
2548   }
2549
2550   /* cues */
2551   if (mux->index != NULL) {
2552     guint n;
2553     guint64 master, pointentry_master, trackpos_master;
2554
2555     mux->cues_pos = ebml->pos;
2556     gst_ebml_write_set_cache (ebml, 12 + 41 * mux->num_indexes);
2557     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CUES);
2558
2559     for (n = 0; n < mux->num_indexes; n++) {
2560       GstMatroskaIndex *idx = &mux->index[n];
2561
2562       pointentry_master = gst_ebml_write_master_start (ebml,
2563           GST_MATROSKA_ID_POINTENTRY);
2564       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETIME,
2565           idx->time / mux->time_scale);
2566       trackpos_master = gst_ebml_write_master_start (ebml,
2567           GST_MATROSKA_ID_CUETRACKPOSITIONS);
2568       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETRACK, idx->track);
2569       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUECLUSTERPOSITION,
2570           idx->pos - mux->segment_master);
2571       gst_ebml_write_master_finish (ebml, trackpos_master);
2572       gst_ebml_write_master_finish (ebml, pointentry_master);
2573     }
2574
2575     gst_ebml_write_master_finish (ebml, master);
2576     gst_ebml_write_flush_cache (ebml, FALSE, GST_CLOCK_TIME_NONE);
2577   }
2578
2579   /* tags */
2580   tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2581
2582   if (tags != NULL && !gst_tag_list_is_empty (tags)) {
2583     guint64 master_tags, master_tag;
2584
2585     GST_DEBUG_OBJECT (mux, "Writing tags");
2586
2587     /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2588     mux->tags_pos = ebml->pos;
2589     master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2590     master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2591     gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2592     gst_ebml_write_master_finish (ebml, master_tag);
2593     gst_ebml_write_master_finish (ebml, master_tags);
2594   }
2595
2596   /* update seekhead. We know that:
2597    * - a seekhead contains 4 entries.
2598    * - order of entries is as above.
2599    * - a seekhead has a 4-byte header + 8-byte length
2600    * - each entry is 2-byte master, 2-byte ID pointer,
2601    *     2-byte length pointer, all 8/1-byte length, 4-
2602    *     byte ID and 8-byte length pointer, where the
2603    *     length pointer starts at 20.
2604    * - all entries are local to the segment (so pos - segment_master).
2605    * - so each entry is at 12 + 20 + num * 28. */
2606   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
2607       mux->info_pos - mux->segment_master);
2608   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
2609       mux->tracks_pos - mux->segment_master);
2610   if (mux->index != NULL) {
2611     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 88,
2612         mux->cues_pos - mux->segment_master);
2613   } else {
2614     /* void'ify */
2615     guint64 my_pos = ebml->pos;
2616
2617     gst_ebml_write_seek (ebml, mux->seekhead_pos + 68);
2618     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2619     gst_ebml_write_seek (ebml, my_pos);
2620   }
2621   if (tags != NULL) {
2622     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 116,
2623         mux->tags_pos - mux->segment_master);
2624   } else {
2625     /* void'ify */
2626     guint64 my_pos = ebml->pos;
2627
2628     gst_ebml_write_seek (ebml, mux->seekhead_pos + 96);
2629     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2630     gst_ebml_write_seek (ebml, my_pos);
2631   }
2632
2633   /* loop tracks:
2634    * - first get the overall duration
2635    *   (a released track may have left a duration in here)
2636    * - write some track header data for subtitles
2637    */
2638   duration = mux->duration;
2639   pos = ebml->pos;
2640   for (collected = mux->collect->data; collected;
2641       collected = g_slist_next (collected)) {
2642     GstMatroskaPad *collect_pad;
2643     GstClockTime min_duration;  /* observed minimum duration */
2644     GstMatroskaTrackContext *context;
2645     gint voidleft = 0, fill = 0;
2646     gpointer codec_id;
2647
2648     collect_pad = (GstMatroskaPad *) collected->data;
2649     context = collect_pad->track;
2650
2651     GST_DEBUG_OBJECT (mux,
2652         "Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
2653         " end ts %" GST_TIME_FORMAT, collect_pad,
2654         GST_TIME_ARGS (collect_pad->start_ts),
2655         GST_TIME_ARGS (collect_pad->end_ts));
2656
2657     if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2658         GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2659       min_duration =
2660           GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2661       if (collect_pad->duration < min_duration)
2662         collect_pad->duration = min_duration;
2663       GST_DEBUG_OBJECT (collect_pad,
2664           "final track duration: %" GST_TIME_FORMAT,
2665           GST_TIME_ARGS (collect_pad->duration));
2666     }
2667
2668     if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
2669         duration < collect_pad->duration)
2670       duration = collect_pad->duration;
2671
2672     if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE || !context->pos)
2673       continue;
2674
2675   again:
2676     /* write subtitle type and possible private data */
2677     gst_ebml_write_seek (ebml, context->pos);
2678     /* complex way to write ascii to account for extra filling */
2679     codec_id = g_malloc0 (strlen (context->codec_id) + 1 + fill);
2680     strcpy (codec_id, context->codec_id);
2681     gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECID,
2682         codec_id, strlen (context->codec_id) + 1 + fill);
2683     g_free (codec_id);
2684     if (context->codec_priv)
2685       gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
2686           context->codec_priv, context->codec_priv_size);
2687     voidleft = SUBTITLE_DUMMY_SIZE - (ebml->pos - context->pos);
2688     /* void'ify; sigh, variable sized length field */
2689     if (voidleft == 1) {
2690       fill = 1;
2691       goto again;
2692     } else if (voidleft && voidleft <= 128)
2693       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 2);
2694     else if (voidleft >= 130)
2695       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 3);
2696     else if (voidleft == 129) {
2697       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 64);
2698       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 63);
2699     }
2700   }
2701
2702   /* seek back (optional, but do anyway) */
2703   gst_ebml_write_seek (ebml, pos);
2704
2705   /* update duration */
2706   if (duration != 0) {
2707     GST_DEBUG_OBJECT (mux, "final total duration: %" GST_TIME_FORMAT,
2708         GST_TIME_ARGS (duration));
2709     pos = mux->ebml_write->pos;
2710     gst_ebml_write_seek (ebml, mux->duration_pos);
2711     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2712         gst_guint64_to_gdouble (duration) /
2713         gst_guint64_to_gdouble (mux->time_scale));
2714     gst_ebml_write_seek (ebml, pos);
2715   } else {
2716     /* void'ify */
2717     guint64 my_pos = ebml->pos;
2718
2719     gst_ebml_write_seek (ebml, mux->duration_pos);
2720     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 8);
2721     gst_ebml_write_seek (ebml, my_pos);
2722   }
2723   GST_DEBUG_OBJECT (mux, "finishing segment");
2724   /* finish segment - this also writes element length */
2725   gst_ebml_write_master_finish (ebml, mux->segment_pos);
2726 }
2727
2728 /**
2729  * gst_matroska_mux_buffer_header:
2730  * @track: Track context.
2731  * @relative_timestamp: relative timestamp of the buffer
2732  * @flags: Buffer flags.
2733  *
2734  * Create a buffer containing buffer header.
2735  *
2736  * Returns: New buffer.
2737  */
2738 static GstBuffer *
2739 gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
2740     gint16 relative_timestamp, int flags)
2741 {
2742   GstBuffer *hdr;
2743   guint8 *data = g_malloc (4);
2744
2745   hdr = gst_buffer_new_wrapped (data, 4);
2746   /* track num - FIXME: what if num >= 0x80 (unlikely)? */
2747   data[0] = track->num | 0x80;
2748   /* time relative to clustertime */
2749   GST_WRITE_UINT16_BE (data + 1, relative_timestamp);
2750
2751   /* flags */
2752   data[3] = flags;
2753
2754   return hdr;
2755 }
2756
2757 #define DIRAC_PARSE_CODE_SEQUENCE_HEADER 0x00
2758 #define DIRAC_PARSE_CODE_END_OF_SEQUENCE 0x10
2759 #define DIRAC_PARSE_CODE_IS_PICTURE(x) ((x & 0x08) != 0)
2760
2761 static GstBuffer *
2762 gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
2763     GstMatroskaPad * collect_pad, GstBuffer * buf)
2764 {
2765   GstMatroskaTrackVideoContext *ctx =
2766       (GstMatroskaTrackVideoContext *) collect_pad->track;
2767   GstMapInfo map;
2768   guint8 *data;
2769   gsize size;
2770   guint8 parse_code;
2771   guint32 next_parse_offset;
2772   GstBuffer *ret = NULL;
2773   gboolean is_muxing_unit = FALSE;
2774
2775   gst_buffer_map (buf, &map, GST_MAP_READ);
2776   data = map.data;
2777   size = map.size;
2778
2779   if (size < 13) {
2780     gst_buffer_unmap (buf, &map);
2781     gst_buffer_unref (buf);
2782     return ret;
2783   }
2784
2785   /* Check if this buffer contains a picture or end-of-sequence packet */
2786   while (size >= 13) {
2787     if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) {
2788       gst_buffer_unmap (buf, &map);
2789       gst_buffer_unref (buf);
2790       return ret;
2791     }
2792
2793     parse_code = GST_READ_UINT8 (data + 4);
2794     if (parse_code == DIRAC_PARSE_CODE_SEQUENCE_HEADER) {
2795       if (ctx->dirac_unit) {
2796         gst_buffer_unref (ctx->dirac_unit);
2797         ctx->dirac_unit = NULL;
2798       }
2799     } else if (DIRAC_PARSE_CODE_IS_PICTURE (parse_code) ||
2800         parse_code == DIRAC_PARSE_CODE_END_OF_SEQUENCE) {
2801       is_muxing_unit = TRUE;
2802       break;
2803     }
2804
2805     next_parse_offset = GST_READ_UINT32_BE (data + 5);
2806
2807     if (G_UNLIKELY (next_parse_offset == 0 || next_parse_offset > size))
2808       break;
2809
2810     data += next_parse_offset;
2811     size -= next_parse_offset;
2812   }
2813
2814   if (ctx->dirac_unit)
2815     ctx->dirac_unit = gst_buffer_join (ctx->dirac_unit, gst_buffer_ref (buf));
2816   else
2817     ctx->dirac_unit = gst_buffer_ref (buf);
2818
2819   gst_buffer_unmap (buf, &map);
2820
2821   if (is_muxing_unit) {
2822     ret = gst_buffer_make_writable (ctx->dirac_unit);
2823     ctx->dirac_unit = NULL;
2824     gst_buffer_copy_into (ret, buf,
2825         GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2826     gst_buffer_unref (buf);
2827   } else {
2828     gst_buffer_unref (buf);
2829     ret = NULL;
2830   }
2831
2832   return ret;
2833 }
2834
2835 static void
2836 gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
2837 {
2838   GstCaps *caps;
2839   GstStructure *s;
2840   GValue streamheader = { 0 };
2841   GValue bufval = { 0 };
2842   GstBuffer *streamheader_buffer;
2843   GstEbmlWrite *ebml = mux->ebml_write;
2844
2845   streamheader_buffer = gst_ebml_stop_streamheader (ebml);
2846   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
2847     caps = gst_caps_new_empty_simple ("video/webm");
2848   } else {
2849     caps = gst_caps_new_empty_simple ("video/x-matroska");
2850   }
2851   s = gst_caps_get_structure (caps, 0);
2852   g_value_init (&streamheader, GST_TYPE_ARRAY);
2853   g_value_init (&bufval, GST_TYPE_BUFFER);
2854   GST_BUFFER_FLAG_SET (streamheader_buffer, GST_BUFFER_FLAG_IN_CAPS);
2855   gst_value_set_buffer (&bufval, streamheader_buffer);
2856   gst_value_array_append_value (&streamheader, &bufval);
2857   g_value_unset (&bufval);
2858   gst_structure_set_value (s, "streamheader", &streamheader);
2859   g_value_unset (&streamheader);
2860   gst_caps_replace (&ebml->caps, caps);
2861   gst_buffer_unref (streamheader_buffer);
2862   gst_caps_unref (caps);
2863 }
2864
2865 /**
2866  * gst_matroska_mux_write_data:
2867  * @mux: #GstMatroskaMux
2868  * @collect_pad: #GstMatroskaPad with the data
2869  *
2870  * Write collected data (called from gst_matroska_mux_collected).
2871  *
2872  * Returns: Result of the gst_pad_push issued to write the data.
2873  */
2874 static GstFlowReturn
2875 gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
2876     GstBuffer * buf)
2877 {
2878   GstEbmlWrite *ebml = mux->ebml_write;
2879   GstBuffer *hdr;
2880   guint64 blockgroup;
2881   gboolean write_duration;
2882   gint16 relative_timestamp;
2883   gint64 relative_timestamp64;
2884   guint64 block_duration;
2885   gboolean is_video_keyframe = FALSE;
2886   GstMatroskamuxPad *pad;
2887
2888   /* write data */
2889   pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
2890
2891   /* vorbis/theora headers are retrieved from caps and put in CodecPrivate */
2892   if (collect_pad->track->xiph_headers_to_skip > 0) {
2893     GST_LOG_OBJECT (collect_pad->collect.pad, "dropping streamheader buffer");
2894     gst_buffer_unref (buf);
2895     --collect_pad->track->xiph_headers_to_skip;
2896     return GST_FLOW_OK;
2897   }
2898
2899   /* for dirac we have to queue up everything up to a picture unit */
2900   if (collect_pad->track->codec_id != NULL &&
2901       strcmp (collect_pad->track->codec_id,
2902           GST_MATROSKA_CODEC_ID_VIDEO_DIRAC) == 0) {
2903     buf = gst_matroska_mux_handle_dirac_packet (mux, collect_pad, buf);
2904     if (!buf)
2905       return GST_FLOW_OK;
2906   }
2907
2908   /* hm, invalid timestamp (due to --to be fixed--- element upstream);
2909    * this would wreak havoc with time stored in matroska file */
2910   /* TODO: maybe calculate a timestamp by using the previous timestamp
2911    * and default duration */
2912   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2913     GST_WARNING_OBJECT (collect_pad->collect.pad,
2914         "Invalid buffer timestamp; dropping buffer");
2915     gst_buffer_unref (buf);
2916     return GST_FLOW_OK;
2917   }
2918
2919   /* set the timestamp for outgoing buffers */
2920   ebml->timestamp = GST_BUFFER_TIMESTAMP (buf);
2921
2922   if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
2923       !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
2924     GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT,
2925         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
2926     is_video_keyframe = TRUE;
2927   }
2928
2929   if (mux->cluster) {
2930     /* start a new cluster at every keyframe, at every GstForceKeyUnit event,
2931      * or when we may be reaching the limit of the relative timestamp */
2932     if (mux->cluster_time +
2933         mux->max_cluster_duration < GST_BUFFER_TIMESTAMP (buf)
2934         || is_video_keyframe || mux->force_key_unit_event) {
2935       if (!mux->streamable)
2936         gst_ebml_write_master_finish (ebml, mux->cluster);
2937
2938       /* Forward the GstForceKeyUnit event after finishing the cluster */
2939       if (mux->force_key_unit_event) {
2940         gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
2941         mux->force_key_unit_event = NULL;
2942       }
2943
2944       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
2945       mux->cluster_pos = ebml->pos;
2946       gst_ebml_write_set_cache (ebml, 0x20);
2947       mux->cluster =
2948           gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2949       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2950           gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
2951               mux->time_scale));
2952       GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
2953           gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
2954               mux->time_scale));
2955       gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
2956       mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2957       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
2958           mux->prev_cluster_size);
2959     }
2960   } else {
2961     /* first cluster */
2962
2963     mux->cluster_pos = ebml->pos;
2964     gst_ebml_write_set_cache (ebml, 0x20);
2965     mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2966     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2967         gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1, mux->time_scale));
2968     gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
2969     mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2970   }
2971
2972   /* update duration of this track */
2973   if (GST_BUFFER_DURATION_IS_VALID (buf))
2974     collect_pad->duration += GST_BUFFER_DURATION (buf);
2975
2976   /* We currently write index entries for all video tracks or for the audio
2977    * track in a single-track audio file.  This could be improved by keeping the
2978    * index only for the *first* video track. */
2979
2980   /* TODO: index is useful for every track, should contain the number of
2981    * the block in the cluster which contains the timestamp, should also work
2982    * for files with multiple audio tracks.
2983    */
2984   if (!mux->streamable &&
2985       (is_video_keyframe ||
2986           ((collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO) &&
2987               (mux->num_streams == 1)))) {
2988     gint last_idx = -1;
2989
2990     if (mux->min_index_interval != 0) {
2991       for (last_idx = mux->num_indexes - 1; last_idx >= 0; last_idx--) {
2992         if (mux->index[last_idx].track == collect_pad->track->num)
2993           break;
2994       }
2995     }
2996
2997     if (last_idx < 0 || mux->min_index_interval == 0 ||
2998         (GST_CLOCK_DIFF (mux->index[last_idx].time, GST_BUFFER_TIMESTAMP (buf))
2999             >= mux->min_index_interval)) {
3000       GstMatroskaIndex *idx;
3001
3002       if (mux->num_indexes % 32 == 0) {
3003         mux->index = g_renew (GstMatroskaIndex, mux->index,
3004             mux->num_indexes + 32);
3005       }
3006       idx = &mux->index[mux->num_indexes++];
3007
3008       idx->pos = mux->cluster_pos;
3009       idx->time = GST_BUFFER_TIMESTAMP (buf);
3010       idx->track = collect_pad->track->num;
3011     }
3012   }
3013
3014   /* Check if the duration differs from the default duration. */
3015   write_duration = FALSE;
3016   block_duration = 0;
3017   if (pad->frame_duration && GST_BUFFER_DURATION_IS_VALID (buf)) {
3018     block_duration = gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
3019         1, mux->time_scale);
3020
3021     /* small difference should be ok. */
3022     if (block_duration > collect_pad->default_duration_scaled + 1 ||
3023         block_duration < collect_pad->default_duration_scaled - 1) {
3024       write_duration = TRUE;
3025     }
3026   }
3027
3028   /* write the block, for doctype v2 use SimpleBlock if possible
3029    * one slice (*breath*).
3030    * FIXME: Need to do correct lacing! */
3031   relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time;
3032   if (relative_timestamp64 >= 0) {
3033     /* round the timestamp */
3034     relative_timestamp64 += gst_util_uint64_scale (mux->time_scale, 1, 2);
3035   } else {
3036     /* round the timestamp */
3037     relative_timestamp64 -= gst_util_uint64_scale (mux->time_scale, 1, 2);
3038   }
3039   relative_timestamp = gst_util_uint64_scale (relative_timestamp64, 1,
3040       mux->time_scale);
3041   if (mux->doctype_version > 1 && !write_duration) {
3042     int flags =
3043         GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : 0x80;
3044
3045     hdr =
3046         gst_matroska_mux_create_buffer_header (collect_pad->track,
3047         relative_timestamp, flags);
3048     gst_ebml_write_set_cache (ebml, 0x40);
3049     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
3050         gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
3051     gst_ebml_write_buffer (ebml, hdr);
3052     gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
3053     gst_ebml_write_buffer (ebml, buf);
3054
3055     return gst_ebml_last_write_result (ebml);
3056   } else {
3057     gst_ebml_write_set_cache (ebml, gst_buffer_get_size (buf) * 2);
3058     /* write and call order slightly unnatural,
3059      * but avoids seek and minizes pushing */
3060     blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
3061     hdr =
3062         gst_matroska_mux_create_buffer_header (collect_pad->track,
3063         relative_timestamp, 0);
3064     if (write_duration)
3065       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
3066     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
3067         gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
3068     gst_ebml_write_buffer (ebml, hdr);
3069     gst_ebml_write_master_finish_full (ebml, blockgroup,
3070         gst_buffer_get_size (buf));
3071     gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
3072     gst_ebml_write_buffer (ebml, buf);
3073
3074     return gst_ebml_last_write_result (ebml);
3075   }
3076 }
3077
3078 /**
3079  * gst_matroska_mux_handle_buffer:
3080  * @pads: #GstCollectPads2
3081  * @uuser_data: #GstMatroskaMux
3082  *
3083  * Collectpads callback.
3084  *
3085  * Returns: #GstFlowReturn
3086  */
3087 static GstFlowReturn
3088 gst_matroska_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
3089     GstBuffer * buf, gpointer user_data)
3090 {
3091   GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
3092   GstEbmlWrite *ebml = mux->ebml_write;
3093   GstMatroskaPad *best;
3094   GstFlowReturn ret = GST_FLOW_OK;
3095
3096   GST_DEBUG_OBJECT (mux, "Collected pads");
3097
3098   /* start with a header */
3099   if (mux->state == GST_MATROSKA_MUX_STATE_START) {
3100     if (mux->collect->data == NULL) {
3101       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
3102           ("No input streams configured"));
3103       return GST_FLOW_ERROR;
3104     }
3105     mux->state = GST_MATROSKA_MUX_STATE_HEADER;
3106     gst_ebml_start_streamheader (ebml);
3107     gst_matroska_mux_start (mux);
3108     gst_matroska_mux_stop_streamheader (mux);
3109     mux->state = GST_MATROSKA_MUX_STATE_DATA;
3110   }
3111
3112   /* provided with stream to write from */
3113   best = (GstMatroskaPad *) data;
3114
3115   /* if there is no best pad, we have reached EOS */
3116   if (best == NULL) {
3117     GST_DEBUG_OBJECT (mux, "No best pad finishing...");
3118     if (!mux->streamable) {
3119       gst_matroska_mux_finish (mux);
3120     } else {
3121       GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
3122     }
3123     gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
3124     ret = GST_FLOW_EOS;
3125     goto exit;
3126   }
3127
3128   /* if we have a best stream, should also have a buffer */
3129   g_assert (buf);
3130
3131   GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
3132       GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
3133       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
3134       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
3135
3136   /* make note of first and last encountered timestamps, so we can calculate
3137    * the actual duration later when we send an updated header on eos */
3138   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
3139     GstClockTime start_ts = GST_BUFFER_TIMESTAMP (buf);
3140     GstClockTime end_ts = start_ts;
3141
3142     if (GST_BUFFER_DURATION_IS_VALID (buf))
3143       end_ts += GST_BUFFER_DURATION (buf);
3144     else if (best->track->default_duration)
3145       end_ts += best->track->default_duration;
3146
3147     if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
3148       best->end_ts = end_ts;
3149
3150     if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
3151             start_ts < best->start_ts))
3152       best->start_ts = start_ts;
3153   }
3154
3155   /* write one buffer */
3156   ret = gst_matroska_mux_write_data (mux, best, buf);
3157
3158 exit:
3159   return ret;
3160 }
3161
3162
3163 /**
3164  * gst_matroska_mux_change_state:
3165  * @element: #GstMatroskaMux
3166  * @transition: State change transition.
3167  *
3168  * Change the muxer state.
3169  *
3170  * Returns: #GstStateChangeReturn
3171  */
3172 static GstStateChangeReturn
3173 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
3174 {
3175   GstStateChangeReturn ret;
3176   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
3177
3178   switch (transition) {
3179     case GST_STATE_CHANGE_NULL_TO_READY:
3180       break;
3181     case GST_STATE_CHANGE_READY_TO_PAUSED:
3182       gst_collect_pads2_start (mux->collect);
3183       break;
3184     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3185       break;
3186     case GST_STATE_CHANGE_PAUSED_TO_READY:
3187       gst_collect_pads2_stop (mux->collect);
3188       break;
3189     default:
3190       break;
3191   }
3192
3193   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3194
3195   switch (transition) {
3196     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3197       break;
3198     case GST_STATE_CHANGE_PAUSED_TO_READY:
3199       gst_matroska_mux_reset (GST_ELEMENT (mux));
3200       break;
3201     case GST_STATE_CHANGE_READY_TO_NULL:
3202       break;
3203     default:
3204       break;
3205   }
3206
3207   return ret;
3208 }
3209
3210 static void
3211 gst_matroska_mux_set_property (GObject * object,
3212     guint prop_id, const GValue * value, GParamSpec * pspec)
3213 {
3214   GstMatroskaMux *mux;
3215
3216   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3217   mux = GST_MATROSKA_MUX (object);
3218
3219   switch (prop_id) {
3220     case ARG_WRITING_APP:
3221       if (!g_value_get_string (value)) {
3222         GST_WARNING_OBJECT (mux, "writing-app property can not be NULL");
3223         break;
3224       }
3225       g_free (mux->writing_app);
3226       mux->writing_app = g_value_dup_string (value);
3227       break;
3228     case ARG_DOCTYPE_VERSION:
3229       mux->doctype_version = g_value_get_int (value);
3230       break;
3231     case ARG_MIN_INDEX_INTERVAL:
3232       mux->min_index_interval = g_value_get_int64 (value);
3233       break;
3234     case ARG_STREAMABLE:
3235       mux->streamable = g_value_get_boolean (value);
3236       break;
3237     default:
3238       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3239       break;
3240   }
3241 }
3242
3243 static void
3244 gst_matroska_mux_get_property (GObject * object,
3245     guint prop_id, GValue * value, GParamSpec * pspec)
3246 {
3247   GstMatroskaMux *mux;
3248
3249   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3250   mux = GST_MATROSKA_MUX (object);
3251
3252   switch (prop_id) {
3253     case ARG_WRITING_APP:
3254       g_value_set_string (value, mux->writing_app);
3255       break;
3256     case ARG_DOCTYPE_VERSION:
3257       g_value_set_int (value, mux->doctype_version);
3258       break;
3259     case ARG_MIN_INDEX_INTERVAL:
3260       g_value_set_int64 (value, mux->min_index_interval);
3261       break;
3262     case ARG_STREAMABLE:
3263       g_value_set_boolean (value, mux->streamable);
3264       break;
3265     default:
3266       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3267       break;
3268   }
3269 }