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