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