matroskamux: create streamable output if downstream is not seekable
[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   }
2380
2381   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
2382     ebml->caps = gst_caps_new_simple ("video/webm", NULL);
2383   } else {
2384     ebml->caps = gst_caps_new_simple ("video/x-matroska", NULL);
2385   }
2386   /* we start with a EBML header */
2387   doctype = mux->doctype;
2388   GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
2389       doctype, mux->doctype_version);
2390   gst_ebml_write_header (ebml, doctype, mux->doctype_version);
2391
2392   /* the rest of the header is cached */
2393   gst_ebml_write_set_cache (ebml, 0x1000);
2394
2395   /* start a segment */
2396   mux->segment_pos =
2397       gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENT);
2398   mux->segment_master = ebml->pos;
2399
2400   if (!mux->streamable) {
2401     /* seekhead (table of contents) - we set the positions later */
2402     mux->seekhead_pos = ebml->pos;
2403     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKHEAD);
2404     for (i = 0; seekhead_id[i] != 0; i++) {
2405       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKENTRY);
2406       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKID, seekhead_id[i]);
2407       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKPOSITION, -1);
2408       gst_ebml_write_master_finish (ebml, child);
2409     }
2410     gst_ebml_write_master_finish (ebml, master);
2411   }
2412
2413   if (mux->streamable) {
2414     const GstTagList *tags;
2415
2416     /* tags */
2417     tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2418
2419     if (tags != NULL && !gst_tag_list_is_empty (tags)) {
2420       guint64 master_tags, master_tag;
2421
2422       GST_DEBUG_OBJECT (mux, "Writing tags");
2423
2424       /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2425       mux->tags_pos = ebml->pos;
2426       master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2427       master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2428       gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2429       gst_ebml_write_master_finish (ebml, master_tag);
2430       gst_ebml_write_master_finish (ebml, master_tags);
2431     }
2432   }
2433
2434   /* segment info */
2435   mux->info_pos = ebml->pos;
2436   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);
2437   for (i = 0; i < 4; i++) {
2438     segment_uid[i] = g_random_int ();
2439   }
2440   gst_ebml_write_binary (ebml, GST_MATROSKA_ID_SEGMENTUID,
2441       (guint8 *) segment_uid, 16);
2442   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TIMECODESCALE, mux->time_scale);
2443   mux->duration_pos = ebml->pos;
2444   /* get duration */
2445   if (!mux->streamable) {
2446     for (collected = mux->collect->data; collected;
2447         collected = g_slist_next (collected)) {
2448       GstMatroskaPad *collect_pad;
2449       GstFormat format = GST_FORMAT_TIME;
2450       GstPad *thepad;
2451       gint64 trackduration;
2452
2453       collect_pad = (GstMatroskaPad *) collected->data;
2454       thepad = collect_pad->collect.pad;
2455
2456       /* Query the total length of the track. */
2457       GST_DEBUG_OBJECT (thepad, "querying peer duration");
2458       if (gst_pad_query_peer_duration (thepad, &format, &trackduration)) {
2459         GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
2460             GST_TIME_ARGS (trackduration));
2461         if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
2462           duration = (GstClockTime) trackduration;
2463         }
2464       }
2465     }
2466     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2467         gst_guint64_to_gdouble (duration) /
2468         gst_guint64_to_gdouble (mux->time_scale));
2469   }
2470   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_MUXINGAPP,
2471       "GStreamer plugin version " PACKAGE_VERSION);
2472   if (mux->writing_app && mux->writing_app[0]) {
2473     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, mux->writing_app);
2474   }
2475   g_get_current_time (&time);
2476   gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time.tv_sec);
2477   gst_ebml_write_master_finish (ebml, master);
2478
2479   /* tracks */
2480   mux->tracks_pos = ebml->pos;
2481   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKS);
2482
2483   for (collected = mux->collect->data; collected;
2484       collected = g_slist_next (collected)) {
2485     GstMatroskaPad *collect_pad;
2486     GstPad *thepad;
2487
2488     collect_pad = (GstMatroskaPad *) collected->data;
2489     thepad = collect_pad->collect.pad;
2490
2491     if (gst_pad_is_linked (thepad) && gst_pad_is_active (thepad) &&
2492         collect_pad->track->codec_id != 0) {
2493       collect_pad->track->num = tracknum++;
2494       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
2495       gst_matroska_mux_track_header (mux, collect_pad->track);
2496       gst_ebml_write_master_finish (ebml, child);
2497       /* some remaining pad/track setup */
2498       collect_pad->default_duration_scaled =
2499           gst_util_uint64_scale (collect_pad->track->default_duration,
2500           1, mux->time_scale);
2501     }
2502   }
2503   gst_ebml_write_master_finish (ebml, master);
2504
2505   /* lastly, flush the cache */
2506   gst_ebml_write_flush_cache (ebml, FALSE, 0);
2507 }
2508
2509 static void
2510 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
2511     gpointer data)
2512 {
2513   /* TODO: more sensible tag mappings */
2514   static const struct
2515   {
2516     const gchar *matroska_tagname;
2517     const gchar *gstreamer_tagname;
2518   }
2519   tag_conv[] = {
2520     {
2521     GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2522     GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
2523     GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2524     GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2525     GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2526     GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2527     GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2528     GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2529     GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2530     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2531     GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2532     GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2533     GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2534     GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2535     GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2536   };
2537   GstEbmlWrite *ebml = (GstEbmlWrite *) data;
2538   guint i;
2539   guint64 simpletag_master;
2540
2541   for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
2542     const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2543     const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2544
2545     if (strcmp (tagname_gst, tag) == 0) {
2546       GValue src = { 0, };
2547       gchar *dest;
2548
2549       if (!gst_tag_list_copy_value (&src, list, tag))
2550         break;
2551       if ((dest = gst_value_serialize (&src))) {
2552
2553         simpletag_master = gst_ebml_write_master_start (ebml,
2554             GST_MATROSKA_ID_SIMPLETAG);
2555         gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_TAGNAME, tagname_mkv);
2556         gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TAGSTRING, dest);
2557         gst_ebml_write_master_finish (ebml, simpletag_master);
2558         g_free (dest);
2559       } else {
2560         GST_WARNING ("Can't transform tag '%s' to string", tagname_mkv);
2561       }
2562       g_value_unset (&src);
2563       break;
2564     }
2565   }
2566 }
2567
2568
2569 /**
2570  * gst_matroska_mux_finish:
2571  * @mux: #GstMatroskaMux
2572  *
2573  * Finish a new matroska file (write index etc...)
2574  */
2575 static void
2576 gst_matroska_mux_finish (GstMatroskaMux * mux)
2577 {
2578   GstEbmlWrite *ebml = mux->ebml_write;
2579   guint64 pos;
2580   guint64 duration = 0;
2581   GSList *collected;
2582   const GstTagList *tags;
2583
2584   /* finish last cluster */
2585   if (mux->cluster) {
2586     gst_ebml_write_master_finish (ebml, mux->cluster);
2587   }
2588
2589   /* cues */
2590   if (mux->index != NULL) {
2591     guint n;
2592     guint64 master, pointentry_master, trackpos_master;
2593
2594     mux->cues_pos = ebml->pos;
2595     gst_ebml_write_set_cache (ebml, 12 + 41 * mux->num_indexes);
2596     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CUES);
2597
2598     for (n = 0; n < mux->num_indexes; n++) {
2599       GstMatroskaIndex *idx = &mux->index[n];
2600
2601       pointentry_master = gst_ebml_write_master_start (ebml,
2602           GST_MATROSKA_ID_POINTENTRY);
2603       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETIME,
2604           idx->time / mux->time_scale);
2605       trackpos_master = gst_ebml_write_master_start (ebml,
2606           GST_MATROSKA_ID_CUETRACKPOSITIONS);
2607       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETRACK, idx->track);
2608       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUECLUSTERPOSITION,
2609           idx->pos - mux->segment_master);
2610       gst_ebml_write_master_finish (ebml, trackpos_master);
2611       gst_ebml_write_master_finish (ebml, pointentry_master);
2612     }
2613
2614     gst_ebml_write_master_finish (ebml, master);
2615     gst_ebml_write_flush_cache (ebml, FALSE, GST_CLOCK_TIME_NONE);
2616   }
2617
2618   /* tags */
2619   tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2620
2621   if (tags != NULL && !gst_tag_list_is_empty (tags)) {
2622     guint64 master_tags, master_tag;
2623
2624     GST_DEBUG_OBJECT (mux, "Writing tags");
2625
2626     /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2627     mux->tags_pos = ebml->pos;
2628     master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2629     master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2630     gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2631     gst_ebml_write_master_finish (ebml, master_tag);
2632     gst_ebml_write_master_finish (ebml, master_tags);
2633   }
2634
2635   /* update seekhead. We know that:
2636    * - a seekhead contains 4 entries.
2637    * - order of entries is as above.
2638    * - a seekhead has a 4-byte header + 8-byte length
2639    * - each entry is 2-byte master, 2-byte ID pointer,
2640    *     2-byte length pointer, all 8/1-byte length, 4-
2641    *     byte ID and 8-byte length pointer, where the
2642    *     length pointer starts at 20.
2643    * - all entries are local to the segment (so pos - segment_master).
2644    * - so each entry is at 12 + 20 + num * 28. */
2645   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
2646       mux->info_pos - mux->segment_master);
2647   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
2648       mux->tracks_pos - mux->segment_master);
2649   if (mux->index != NULL) {
2650     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 88,
2651         mux->cues_pos - mux->segment_master);
2652   } else {
2653     /* void'ify */
2654     guint64 my_pos = ebml->pos;
2655
2656     gst_ebml_write_seek (ebml, mux->seekhead_pos + 68);
2657     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2658     gst_ebml_write_seek (ebml, my_pos);
2659   }
2660   if (tags != NULL) {
2661     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 116,
2662         mux->tags_pos - mux->segment_master);
2663   } else {
2664     /* void'ify */
2665     guint64 my_pos = ebml->pos;
2666
2667     gst_ebml_write_seek (ebml, mux->seekhead_pos + 96);
2668     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2669     gst_ebml_write_seek (ebml, my_pos);
2670   }
2671
2672   /* loop tracks:
2673    * - first get the overall duration
2674    *   (a released track may have left a duration in here)
2675    * - write some track header data for subtitles
2676    */
2677   duration = mux->duration;
2678   pos = ebml->pos;
2679   for (collected = mux->collect->data; collected;
2680       collected = g_slist_next (collected)) {
2681     GstMatroskaPad *collect_pad;
2682     GstClockTime min_duration;  /* observed minimum duration */
2683     GstMatroskaTrackContext *context;
2684     gint voidleft = 0, fill = 0;
2685     gpointer codec_id;
2686
2687     collect_pad = (GstMatroskaPad *) collected->data;
2688     context = collect_pad->track;
2689
2690     GST_DEBUG_OBJECT (mux,
2691         "Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
2692         " end ts %" GST_TIME_FORMAT, collect_pad,
2693         GST_TIME_ARGS (collect_pad->start_ts),
2694         GST_TIME_ARGS (collect_pad->end_ts));
2695
2696     if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2697         GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2698       min_duration =
2699           GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2700       if (collect_pad->duration < min_duration)
2701         collect_pad->duration = min_duration;
2702       GST_DEBUG_OBJECT (collect_pad,
2703           "final track duration: %" GST_TIME_FORMAT,
2704           GST_TIME_ARGS (collect_pad->duration));
2705     }
2706
2707     if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
2708         duration < collect_pad->duration)
2709       duration = collect_pad->duration;
2710
2711     if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE || !context->pos)
2712       continue;
2713
2714   again:
2715     /* write subtitle type and possible private data */
2716     gst_ebml_write_seek (ebml, context->pos);
2717     /* complex way to write ascii to account for extra filling */
2718     codec_id = g_malloc0 (strlen (context->codec_id) + 1 + fill);
2719     strcpy (codec_id, context->codec_id);
2720     gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECID,
2721         codec_id, strlen (context->codec_id) + 1 + fill);
2722     g_free (codec_id);
2723     if (context->codec_priv)
2724       gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
2725           context->codec_priv, context->codec_priv_size);
2726     voidleft = SUBTITLE_DUMMY_SIZE - (ebml->pos - context->pos);
2727     /* void'ify; sigh, variable sized length field */
2728     if (voidleft == 1) {
2729       fill = 1;
2730       goto again;
2731     } else if (voidleft && voidleft <= 128)
2732       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 2);
2733     else if (voidleft >= 130)
2734       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 3);
2735     else if (voidleft == 129) {
2736       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 64);
2737       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 63);
2738     }
2739   }
2740
2741   /* seek back (optional, but do anyway) */
2742   gst_ebml_write_seek (ebml, pos);
2743
2744   /* update duration */
2745   if (duration != 0) {
2746     GST_DEBUG_OBJECT (mux, "final total duration: %" GST_TIME_FORMAT,
2747         GST_TIME_ARGS (duration));
2748     pos = mux->ebml_write->pos;
2749     gst_ebml_write_seek (ebml, mux->duration_pos);
2750     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2751         gst_guint64_to_gdouble (duration) /
2752         gst_guint64_to_gdouble (mux->time_scale));
2753     gst_ebml_write_seek (ebml, pos);
2754   } else {
2755     /* void'ify */
2756     guint64 my_pos = ebml->pos;
2757
2758     gst_ebml_write_seek (ebml, mux->duration_pos);
2759     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 8);
2760     gst_ebml_write_seek (ebml, my_pos);
2761   }
2762   GST_DEBUG_OBJECT (mux, "finishing segment");
2763   /* finish segment - this also writes element length */
2764   gst_ebml_write_master_finish (ebml, mux->segment_pos);
2765 }
2766
2767 /**
2768  * gst_matroska_mux_buffer_header:
2769  * @track: Track context.
2770  * @relative_timestamp: relative timestamp of the buffer
2771  * @flags: Buffer flags.
2772  *
2773  * Create a buffer containing buffer header.
2774  *
2775  * Returns: New buffer.
2776  */
2777 static GstBuffer *
2778 gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
2779     gint16 relative_timestamp, int flags)
2780 {
2781   GstBuffer *hdr;
2782
2783   hdr = gst_buffer_new_and_alloc (4);
2784   /* track num - FIXME: what if num >= 0x80 (unlikely)? */
2785   GST_BUFFER_DATA (hdr)[0] = track->num | 0x80;
2786   /* time relative to clustertime */
2787   GST_WRITE_UINT16_BE (GST_BUFFER_DATA (hdr) + 1, relative_timestamp);
2788
2789   /* flags */
2790   GST_BUFFER_DATA (hdr)[3] = flags;
2791
2792   return hdr;
2793 }
2794
2795 #define DIRAC_PARSE_CODE_SEQUENCE_HEADER 0x00
2796 #define DIRAC_PARSE_CODE_END_OF_SEQUENCE 0x10
2797 #define DIRAC_PARSE_CODE_IS_PICTURE(x) ((x & 0x08) != 0)
2798
2799 static GstBuffer *
2800 gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
2801     GstMatroskaPad * collect_pad, GstBuffer * buf)
2802 {
2803   GstMatroskaTrackVideoContext *ctx =
2804       (GstMatroskaTrackVideoContext *) collect_pad->track;
2805   const guint8 *data = GST_BUFFER_DATA (buf);
2806   guint size = GST_BUFFER_SIZE (buf);
2807   guint8 parse_code;
2808   guint32 next_parse_offset;
2809   GstBuffer *ret = NULL;
2810   gboolean is_muxing_unit = FALSE;
2811
2812   if (GST_BUFFER_SIZE (buf) < 13) {
2813     gst_buffer_unref (buf);
2814     return ret;
2815   }
2816
2817   /* Check if this buffer contains a picture or end-of-sequence packet */
2818   while (size >= 13) {
2819     if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) {
2820       gst_buffer_unref (buf);
2821       return ret;
2822     }
2823
2824     parse_code = GST_READ_UINT8 (data + 4);
2825     if (parse_code == DIRAC_PARSE_CODE_SEQUENCE_HEADER) {
2826       if (ctx->dirac_unit) {
2827         gst_buffer_unref (ctx->dirac_unit);
2828         ctx->dirac_unit = NULL;
2829       }
2830     } else if (DIRAC_PARSE_CODE_IS_PICTURE (parse_code) ||
2831         parse_code == DIRAC_PARSE_CODE_END_OF_SEQUENCE) {
2832       is_muxing_unit = TRUE;
2833       break;
2834     }
2835
2836     next_parse_offset = GST_READ_UINT32_BE (data + 5);
2837
2838     if (G_UNLIKELY (next_parse_offset == 0 || next_parse_offset > size))
2839       break;
2840
2841     data += next_parse_offset;
2842     size -= next_parse_offset;
2843   }
2844
2845   if (ctx->dirac_unit)
2846     ctx->dirac_unit = gst_buffer_join (ctx->dirac_unit, gst_buffer_ref (buf));
2847   else
2848     ctx->dirac_unit = gst_buffer_ref (buf);
2849
2850   if (is_muxing_unit) {
2851     ret = gst_buffer_make_metadata_writable (ctx->dirac_unit);
2852     ctx->dirac_unit = NULL;
2853     gst_buffer_copy_metadata (ret, buf,
2854         GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
2855         GST_BUFFER_COPY_CAPS);
2856     gst_buffer_unref (buf);
2857   } else {
2858     gst_buffer_unref (buf);
2859     ret = NULL;
2860   }
2861
2862   return ret;
2863 }
2864
2865 static void
2866 gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
2867 {
2868   GstCaps *caps;
2869   GstStructure *s;
2870   GValue streamheader = { 0 };
2871   GValue bufval = { 0 };
2872   GstBuffer *streamheader_buffer;
2873   GstEbmlWrite *ebml = mux->ebml_write;
2874
2875   streamheader_buffer = gst_ebml_stop_streamheader (ebml);
2876   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
2877     caps = gst_caps_new_simple ("video/webm", NULL);
2878   } else {
2879     caps = gst_caps_new_simple ("video/x-matroska", NULL);
2880   }
2881   s = gst_caps_get_structure (caps, 0);
2882   g_value_init (&streamheader, GST_TYPE_ARRAY);
2883   g_value_init (&bufval, GST_TYPE_BUFFER);
2884   GST_BUFFER_FLAG_SET (streamheader_buffer, GST_BUFFER_FLAG_IN_CAPS);
2885   gst_value_set_buffer (&bufval, streamheader_buffer);
2886   gst_value_array_append_value (&streamheader, &bufval);
2887   g_value_unset (&bufval);
2888   gst_structure_set_value (s, "streamheader", &streamheader);
2889   g_value_unset (&streamheader);
2890   gst_caps_replace (&ebml->caps, caps);
2891   gst_buffer_unref (streamheader_buffer);
2892   gst_caps_unref (caps);
2893 }
2894
2895 /**
2896  * gst_matroska_mux_write_data:
2897  * @mux: #GstMatroskaMux
2898  * @collect_pad: #GstMatroskaPad with the data
2899  *
2900  * Write collected data (called from gst_matroska_mux_collected).
2901  *
2902  * Returns: Result of the gst_pad_push issued to write the data.
2903  */
2904 static GstFlowReturn
2905 gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
2906     GstBuffer * buf)
2907 {
2908   GstEbmlWrite *ebml = mux->ebml_write;
2909   GstBuffer *hdr;
2910   guint64 blockgroup;
2911   gboolean write_duration;
2912   gint16 relative_timestamp;
2913   gint64 relative_timestamp64;
2914   guint64 block_duration;
2915   gboolean is_video_keyframe = FALSE;
2916   GstMatroskamuxPad *pad;
2917
2918   /* write data */
2919   pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
2920
2921   /* vorbis/theora headers are retrieved from caps and put in CodecPrivate */
2922   if (collect_pad->track->xiph_headers_to_skip > 0) {
2923     GST_LOG_OBJECT (collect_pad->collect.pad, "dropping streamheader buffer");
2924     gst_buffer_unref (buf);
2925     --collect_pad->track->xiph_headers_to_skip;
2926     return GST_FLOW_OK;
2927   }
2928
2929   /* for dirac we have to queue up everything up to a picture unit */
2930   if (collect_pad->track->codec_id != NULL &&
2931       strcmp (collect_pad->track->codec_id,
2932           GST_MATROSKA_CODEC_ID_VIDEO_DIRAC) == 0) {
2933     buf = gst_matroska_mux_handle_dirac_packet (mux, collect_pad, buf);
2934     if (!buf)
2935       return GST_FLOW_OK;
2936   }
2937
2938   /* hm, invalid timestamp (due to --to be fixed--- element upstream);
2939    * this would wreak havoc with time stored in matroska file */
2940   /* TODO: maybe calculate a timestamp by using the previous timestamp
2941    * and default duration */
2942   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2943     GST_WARNING_OBJECT (collect_pad->collect.pad,
2944         "Invalid buffer timestamp; dropping buffer");
2945     gst_buffer_unref (buf);
2946     return GST_FLOW_OK;
2947   }
2948
2949   /* set the timestamp for outgoing buffers */
2950   ebml->timestamp = GST_BUFFER_TIMESTAMP (buf);
2951
2952   if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
2953       !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
2954     GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT,
2955         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
2956     is_video_keyframe = TRUE;
2957   }
2958
2959   if (mux->cluster) {
2960     /* start a new cluster at every keyframe, at every GstForceKeyUnit event,
2961      * or when we may be reaching the limit of the relative timestamp */
2962     if (mux->cluster_time +
2963         mux->max_cluster_duration < GST_BUFFER_TIMESTAMP (buf)
2964         || is_video_keyframe || mux->force_key_unit_event) {
2965       if (!mux->streamable)
2966         gst_ebml_write_master_finish (ebml, mux->cluster);
2967
2968       /* Forward the GstForceKeyUnit event after finishing the cluster */
2969       if (mux->force_key_unit_event) {
2970         gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
2971         mux->force_key_unit_event = NULL;
2972       }
2973
2974       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
2975       mux->cluster_pos = ebml->pos;
2976       gst_ebml_write_set_cache (ebml, 0x20);
2977       mux->cluster =
2978           gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2979       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2980           gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
2981               mux->time_scale));
2982       GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
2983           gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
2984               mux->time_scale));
2985       gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
2986       mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2987       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
2988           mux->prev_cluster_size);
2989     }
2990   } else {
2991     /* first cluster */
2992
2993     mux->cluster_pos = ebml->pos;
2994     gst_ebml_write_set_cache (ebml, 0x20);
2995     mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2996     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2997         gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1, mux->time_scale));
2998     gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
2999     mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
3000   }
3001
3002   /* update duration of this track */
3003   if (GST_BUFFER_DURATION_IS_VALID (buf))
3004     collect_pad->duration += GST_BUFFER_DURATION (buf);
3005
3006   /* We currently write index entries for all video tracks or for the audio
3007    * track in a single-track audio file.  This could be improved by keeping the
3008    * index only for the *first* video track. */
3009
3010   /* TODO: index is useful for every track, should contain the number of
3011    * the block in the cluster which contains the timestamp, should also work
3012    * for files with multiple audio tracks.
3013    */
3014   if (!mux->streamable &&
3015       (is_video_keyframe ||
3016           ((collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO) &&
3017               (mux->num_streams == 1)))) {
3018     gint last_idx = -1;
3019
3020     if (mux->min_index_interval != 0) {
3021       for (last_idx = mux->num_indexes - 1; last_idx >= 0; last_idx--) {
3022         if (mux->index[last_idx].track == collect_pad->track->num)
3023           break;
3024       }
3025     }
3026
3027     if (last_idx < 0 || mux->min_index_interval == 0 ||
3028         (GST_CLOCK_DIFF (mux->index[last_idx].time, GST_BUFFER_TIMESTAMP (buf))
3029             >= mux->min_index_interval)) {
3030       GstMatroskaIndex *idx;
3031
3032       if (mux->num_indexes % 32 == 0) {
3033         mux->index = g_renew (GstMatroskaIndex, mux->index,
3034             mux->num_indexes + 32);
3035       }
3036       idx = &mux->index[mux->num_indexes++];
3037
3038       idx->pos = mux->cluster_pos;
3039       idx->time = GST_BUFFER_TIMESTAMP (buf);
3040       idx->track = collect_pad->track->num;
3041     }
3042   }
3043
3044   /* Check if the duration differs from the default duration. */
3045   write_duration = FALSE;
3046   block_duration = 0;
3047   if (pad->frame_duration && GST_BUFFER_DURATION_IS_VALID (buf)) {
3048     block_duration = gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
3049         1, mux->time_scale);
3050
3051     /* small difference should be ok. */
3052     if (block_duration > collect_pad->default_duration_scaled + 1 ||
3053         block_duration < collect_pad->default_duration_scaled - 1) {
3054       write_duration = TRUE;
3055     }
3056   }
3057
3058   /* write the block, for doctype v2 use SimpleBlock if possible
3059    * one slice (*breath*).
3060    * FIXME: Need to do correct lacing! */
3061   relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time;
3062   if (relative_timestamp64 >= 0) {
3063     /* round the timestamp */
3064     relative_timestamp64 += gst_util_uint64_scale (mux->time_scale, 1, 2);
3065   } else {
3066     /* round the timestamp */
3067     relative_timestamp64 -= gst_util_uint64_scale (mux->time_scale, 1, 2);
3068   }
3069   relative_timestamp = gst_util_uint64_scale (relative_timestamp64, 1,
3070       mux->time_scale);
3071   if (mux->doctype_version > 1 && !write_duration) {
3072     int flags =
3073         GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : 0x80;
3074
3075     hdr =
3076         gst_matroska_mux_create_buffer_header (collect_pad->track,
3077         relative_timestamp, flags);
3078     gst_ebml_write_set_cache (ebml, 0x40);
3079     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
3080         GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
3081     gst_ebml_write_buffer (ebml, hdr);
3082     gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
3083     gst_ebml_write_buffer (ebml, buf);
3084
3085     return gst_ebml_last_write_result (ebml);
3086   } else {
3087     gst_ebml_write_set_cache (ebml, GST_BUFFER_SIZE (buf) * 2);
3088     /* write and call order slightly unnatural,
3089      * but avoids seek and minizes pushing */
3090     blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
3091     hdr =
3092         gst_matroska_mux_create_buffer_header (collect_pad->track,
3093         relative_timestamp, 0);
3094     if (write_duration)
3095       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
3096     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
3097         GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
3098     gst_ebml_write_buffer (ebml, hdr);
3099     gst_ebml_write_master_finish_full (ebml, blockgroup, GST_BUFFER_SIZE (buf));
3100     gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
3101     gst_ebml_write_buffer (ebml, buf);
3102
3103     return gst_ebml_last_write_result (ebml);
3104   }
3105 }
3106
3107 /**
3108  * gst_matroska_mux_handle_buffer:
3109  * @pads: #GstCollectPads2
3110  * @uuser_data: #GstMatroskaMux
3111  *
3112  * Collectpads callback.
3113  *
3114  * Returns: #GstFlowReturn
3115  */
3116 static GstFlowReturn
3117 gst_matroska_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
3118     GstBuffer * buf, gpointer user_data)
3119 {
3120   GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
3121   GstEbmlWrite *ebml = mux->ebml_write;
3122   GstMatroskaPad *best;
3123   GstFlowReturn ret = GST_FLOW_OK;
3124
3125   GST_DEBUG_OBJECT (mux, "Collected pads");
3126
3127   /* start with a header */
3128   if (mux->state == GST_MATROSKA_MUX_STATE_START) {
3129     if (mux->collect->data == NULL) {
3130       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
3131           ("No input streams configured"));
3132       return GST_FLOW_ERROR;
3133     }
3134     mux->state = GST_MATROSKA_MUX_STATE_HEADER;
3135     gst_ebml_start_streamheader (ebml);
3136     gst_matroska_mux_start (mux);
3137     gst_matroska_mux_stop_streamheader (mux);
3138     mux->state = GST_MATROSKA_MUX_STATE_DATA;
3139   }
3140
3141   /* provided with stream to write from */
3142   best = (GstMatroskaPad *) data;
3143
3144   /* if there is no best pad, we have reached EOS */
3145   if (best == NULL) {
3146     GST_DEBUG_OBJECT (mux, "No best pad finishing...");
3147     if (!mux->streamable) {
3148       gst_matroska_mux_finish (mux);
3149     } else {
3150       GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
3151     }
3152     gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
3153     ret = GST_FLOW_UNEXPECTED;
3154     goto exit;
3155   }
3156
3157   /* if we have a best stream, should also have a buffer */
3158   g_assert (buf);
3159
3160   GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
3161       GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
3162       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
3163       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
3164
3165   /* make note of first and last encountered timestamps, so we can calculate
3166    * the actual duration later when we send an updated header on eos */
3167   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
3168     GstClockTime start_ts = GST_BUFFER_TIMESTAMP (buf);
3169     GstClockTime end_ts = start_ts;
3170
3171     if (GST_BUFFER_DURATION_IS_VALID (buf))
3172       end_ts += GST_BUFFER_DURATION (buf);
3173     else if (best->track->default_duration)
3174       end_ts += best->track->default_duration;
3175
3176     if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
3177       best->end_ts = end_ts;
3178
3179     if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
3180             start_ts < best->start_ts))
3181       best->start_ts = start_ts;
3182   }
3183
3184   /* write one buffer */
3185   ret = gst_matroska_mux_write_data (mux, best, buf);
3186
3187 exit:
3188   return ret;
3189 }
3190
3191
3192 /**
3193  * gst_matroska_mux_change_state:
3194  * @element: #GstMatroskaMux
3195  * @transition: State change transition.
3196  *
3197  * Change the muxer state.
3198  *
3199  * Returns: #GstStateChangeReturn
3200  */
3201 static GstStateChangeReturn
3202 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
3203 {
3204   GstStateChangeReturn ret;
3205   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
3206
3207   switch (transition) {
3208     case GST_STATE_CHANGE_NULL_TO_READY:
3209       break;
3210     case GST_STATE_CHANGE_READY_TO_PAUSED:
3211       gst_collect_pads2_start (mux->collect);
3212       break;
3213     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3214       break;
3215     case GST_STATE_CHANGE_PAUSED_TO_READY:
3216       gst_collect_pads2_stop (mux->collect);
3217       break;
3218     default:
3219       break;
3220   }
3221
3222   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3223
3224   switch (transition) {
3225     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3226       break;
3227     case GST_STATE_CHANGE_PAUSED_TO_READY:
3228       gst_matroska_mux_reset (GST_ELEMENT (mux));
3229       break;
3230     case GST_STATE_CHANGE_READY_TO_NULL:
3231       break;
3232     default:
3233       break;
3234   }
3235
3236   return ret;
3237 }
3238
3239 static void
3240 gst_matroska_mux_set_property (GObject * object,
3241     guint prop_id, const GValue * value, GParamSpec * pspec)
3242 {
3243   GstMatroskaMux *mux;
3244
3245   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3246   mux = GST_MATROSKA_MUX (object);
3247
3248   switch (prop_id) {
3249     case ARG_WRITING_APP:
3250       if (!g_value_get_string (value)) {
3251         GST_WARNING_OBJECT (mux, "writing-app property can not be NULL");
3252         break;
3253       }
3254       g_free (mux->writing_app);
3255       mux->writing_app = g_value_dup_string (value);
3256       break;
3257     case ARG_DOCTYPE_VERSION:
3258       mux->doctype_version = g_value_get_int (value);
3259       break;
3260     case ARG_MIN_INDEX_INTERVAL:
3261       mux->min_index_interval = g_value_get_int64 (value);
3262       break;
3263     case ARG_STREAMABLE:
3264       mux->streamable = g_value_get_boolean (value);
3265       break;
3266     default:
3267       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3268       break;
3269   }
3270 }
3271
3272 static void
3273 gst_matroska_mux_get_property (GObject * object,
3274     guint prop_id, GValue * value, GParamSpec * pspec)
3275 {
3276   GstMatroskaMux *mux;
3277
3278   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3279   mux = GST_MATROSKA_MUX (object);
3280
3281   switch (prop_id) {
3282     case ARG_WRITING_APP:
3283       g_value_set_string (value, mux->writing_app);
3284       break;
3285     case ARG_DOCTYPE_VERSION:
3286       g_value_set_int (value, mux->doctype_version);
3287       break;
3288     case ARG_MIN_INDEX_INTERVAL:
3289       g_value_set_int64 (value, mux->min_index_interval);
3290       break;
3291     case ARG_STREAMABLE:
3292       g_value_set_boolean (value, mux->streamable);
3293       break;
3294     default:
3295       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3296       break;
3297   }
3298 }