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