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