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