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