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