matroskamux: no need to set cache twice
[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
2009   /* we start with a EBML header */
2010   doctype = mux->doctype;
2011   GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
2012       doctype, mux->doctype_version);
2013   gst_ebml_write_header (ebml, doctype, mux->doctype_version);
2014
2015   /* the rest of the header is cached */
2016   gst_ebml_write_set_cache (ebml, 0x1000);
2017
2018   /* start a segment */
2019   mux->segment_pos =
2020       gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENT);
2021   mux->segment_master = ebml->pos;
2022
2023   if (!mux->is_live) {
2024     /* seekhead (table of contents) - we set the positions later */
2025     mux->seekhead_pos = ebml->pos;
2026     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKHEAD);
2027     for (i = 0; seekhead_id[i] != 0; i++) {
2028       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKENTRY);
2029       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKID, seekhead_id[i]);
2030       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKPOSITION, -1);
2031       gst_ebml_write_master_finish (ebml, child);
2032     }
2033     gst_ebml_write_master_finish (ebml, master);
2034   }
2035
2036   /* segment info */
2037   mux->info_pos = ebml->pos;
2038   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);
2039   for (i = 0; i < 4; i++) {
2040     segment_uid[i] = g_random_int ();
2041   }
2042   gst_ebml_write_binary (ebml, GST_MATROSKA_ID_SEGMENTUID,
2043       (guint8 *) segment_uid, 16);
2044   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TIMECODESCALE, mux->time_scale);
2045   mux->duration_pos = ebml->pos;
2046   /* get duration */
2047   for (collected = mux->collect->data; collected;
2048       collected = g_slist_next (collected)) {
2049     GstMatroskaPad *collect_pad;
2050     GstFormat format = GST_FORMAT_TIME;
2051     GstPad *thepad;
2052     gint64 trackduration;
2053
2054     collect_pad = (GstMatroskaPad *) collected->data;
2055     thepad = collect_pad->collect.pad;
2056
2057     /* Query the total length of the track. */
2058     GST_DEBUG_OBJECT (thepad, "querying peer duration");
2059     if (gst_pad_query_peer_duration (thepad, &format, &trackduration)) {
2060       GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
2061           GST_TIME_ARGS (trackduration));
2062       if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
2063         duration = (GstClockTime) trackduration;
2064       }
2065     }
2066   }
2067   gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2068       gst_guint64_to_gdouble (duration) /
2069       gst_guint64_to_gdouble (mux->time_scale));
2070
2071   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_MUXINGAPP,
2072       "GStreamer plugin version " PACKAGE_VERSION);
2073   if (mux->writing_app && mux->writing_app[0]) {
2074     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, mux->writing_app);
2075   }
2076   g_get_current_time (&time);
2077   gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time.tv_sec);
2078   gst_ebml_write_master_finish (ebml, master);
2079
2080   /* tracks */
2081   mux->tracks_pos = ebml->pos;
2082   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKS);
2083
2084   for (collected = mux->collect->data; collected;
2085       collected = g_slist_next (collected)) {
2086     GstMatroskaPad *collect_pad;
2087     GstPad *thepad;
2088
2089     collect_pad = (GstMatroskaPad *) collected->data;
2090     thepad = collect_pad->collect.pad;
2091
2092     if (gst_pad_is_linked (thepad) && gst_pad_is_active (thepad) &&
2093         collect_pad->track->codec_id != 0) {
2094       collect_pad->track->num = tracknum++;
2095       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
2096       gst_matroska_mux_track_header (mux, collect_pad->track);
2097       gst_ebml_write_master_finish (ebml, child);
2098     }
2099   }
2100   gst_ebml_write_master_finish (ebml, master);
2101
2102   /* lastly, flush the cache */
2103   gst_ebml_write_flush_cache (ebml);
2104 }
2105
2106 static void
2107 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
2108     gpointer data)
2109 {
2110   /* TODO: more sensible tag mappings */
2111   struct
2112   {
2113     const gchar *matroska_tagname;
2114     const gchar *gstreamer_tagname;
2115   }
2116   tag_conv[] = {
2117     {
2118     GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2119     GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
2120     GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2121     GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2122     GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2123     GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2124     GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2125     GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2126     GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2127     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2128     GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2129     GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2130     GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2131     GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2132     GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2133   };
2134   GstEbmlWrite *ebml = (GstEbmlWrite *) data;
2135   guint i;
2136   guint64 simpletag_master;
2137
2138   for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
2139     const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2140     const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2141
2142     if (strcmp (tagname_gst, tag) == 0) {
2143       GValue src = { 0, };
2144       gchar *dest;
2145
2146       if (!gst_tag_list_copy_value (&src, list, tag))
2147         break;
2148       if ((dest = gst_value_serialize (&src))) {
2149
2150         simpletag_master = gst_ebml_write_master_start (ebml,
2151             GST_MATROSKA_ID_SIMPLETAG);
2152         gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_TAGNAME, tagname_mkv);
2153         gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TAGSTRING, dest);
2154         gst_ebml_write_master_finish (ebml, simpletag_master);
2155         g_free (dest);
2156       } else {
2157         GST_WARNING ("Can't transform tag '%s' to string", tagname_mkv);
2158       }
2159       g_value_unset (&src);
2160       break;
2161     }
2162   }
2163 }
2164
2165
2166 /**
2167  * gst_matroska_mux_finish:
2168  * @mux: #GstMatroskaMux
2169  *
2170  * Finish a new matroska file (write index etc...)
2171  */
2172 static void
2173 gst_matroska_mux_finish (GstMatroskaMux * mux)
2174 {
2175   GstEbmlWrite *ebml = mux->ebml_write;
2176   guint64 pos;
2177   guint64 duration = 0;
2178   GSList *collected;
2179   const GstTagList *tags;
2180
2181   /* finish last cluster */
2182   if (mux->cluster) {
2183     gst_ebml_write_master_finish (ebml, mux->cluster);
2184   }
2185
2186   /* cues */
2187   if (mux->index != NULL && !mux->is_live) {
2188     guint n;
2189     guint64 master, pointentry_master, trackpos_master;
2190
2191     mux->cues_pos = ebml->pos;
2192     gst_ebml_write_set_cache (ebml, 12 + 41 * mux->num_indexes);
2193     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CUES);
2194
2195     for (n = 0; n < mux->num_indexes; n++) {
2196       GstMatroskaIndex *idx = &mux->index[n];
2197
2198       pointentry_master = gst_ebml_write_master_start (ebml,
2199           GST_MATROSKA_ID_POINTENTRY);
2200       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETIME,
2201           idx->time / mux->time_scale);
2202       trackpos_master = gst_ebml_write_master_start (ebml,
2203           GST_MATROSKA_ID_CUETRACKPOSITIONS);
2204       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETRACK, idx->track);
2205       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUECLUSTERPOSITION,
2206           idx->pos - mux->segment_master);
2207       gst_ebml_write_master_finish (ebml, trackpos_master);
2208       gst_ebml_write_master_finish (ebml, pointentry_master);
2209     }
2210
2211     gst_ebml_write_master_finish (ebml, master);
2212     gst_ebml_write_flush_cache (ebml);
2213   }
2214
2215   /* tags */
2216   tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2217
2218   if (tags != NULL && !gst_tag_list_is_empty (tags) && !mux->is_live) {
2219     guint64 master_tags, master_tag;
2220
2221     GST_DEBUG ("Writing tags");
2222
2223     /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2224     mux->tags_pos = ebml->pos;
2225     master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2226     master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2227     gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2228     gst_ebml_write_master_finish (ebml, master_tag);
2229     gst_ebml_write_master_finish (ebml, master_tags);
2230   }
2231
2232   /* update seekhead. We know that:
2233    * - a seekhead contains 4 entries.
2234    * - order of entries is as above.
2235    * - a seekhead has a 4-byte header + 8-byte length
2236    * - each entry is 2-byte master, 2-byte ID pointer,
2237    *     2-byte length pointer, all 8/1-byte length, 4-
2238    *     byte ID and 8-byte length pointer, where the
2239    *     length pointer starts at 20.
2240    * - all entries are local to the segment (so pos - segment_master).
2241    * - so each entry is at 12 + 20 + num * 28. */
2242   if (!mux->is_live) {
2243     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
2244         mux->info_pos - mux->segment_master);
2245     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
2246         mux->tracks_pos - mux->segment_master);
2247     if (mux->index != NULL) {
2248       gst_ebml_replace_uint (ebml, mux->seekhead_pos + 88,
2249           mux->cues_pos - mux->segment_master);
2250     } else {
2251       /* void'ify */
2252       guint64 my_pos = ebml->pos;
2253
2254       gst_ebml_write_seek (ebml, mux->seekhead_pos + 68);
2255       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2256       gst_ebml_write_seek (ebml, my_pos);
2257     }
2258     if (tags != NULL) {
2259       gst_ebml_replace_uint (ebml, mux->seekhead_pos + 116,
2260           mux->tags_pos - mux->segment_master);
2261     } else {
2262       /* void'ify */
2263       guint64 my_pos = ebml->pos;
2264
2265       gst_ebml_write_seek (ebml, mux->seekhead_pos + 96);
2266       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2267       gst_ebml_write_seek (ebml, my_pos);
2268     }
2269
2270     /* update duration */
2271     /* first get the overall duration */
2272     /* a released track may have left a duration in here */
2273     duration = mux->duration;
2274     for (collected = mux->collect->data; collected;
2275         collected = g_slist_next (collected)) {
2276       GstMatroskaPad *collect_pad;
2277       GstClockTime min_duration;        /* observed minimum duration */
2278
2279       collect_pad = (GstMatroskaPad *) collected->data;
2280
2281       GST_DEBUG_OBJECT (mux,
2282           "Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
2283           " end ts %" GST_TIME_FORMAT, collect_pad,
2284           GST_TIME_ARGS (collect_pad->start_ts),
2285           GST_TIME_ARGS (collect_pad->end_ts));
2286
2287       if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2288           GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2289         min_duration =
2290             GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2291         if (collect_pad->duration < min_duration)
2292           collect_pad->duration = min_duration;
2293         GST_DEBUG_OBJECT (collect_pad,
2294             "final track duration: %" GST_TIME_FORMAT,
2295             GST_TIME_ARGS (collect_pad->duration));
2296       }
2297
2298       if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
2299           duration < collect_pad->duration)
2300         duration = collect_pad->duration;
2301     }
2302     if (duration != 0) {
2303       GST_DEBUG_OBJECT (mux, "final total duration: %" GST_TIME_FORMAT,
2304           GST_TIME_ARGS (duration));
2305       pos = mux->ebml_write->pos;
2306       gst_ebml_write_seek (ebml, mux->duration_pos);
2307       gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2308           gst_guint64_to_gdouble (duration) /
2309           gst_guint64_to_gdouble (mux->time_scale));
2310       gst_ebml_write_seek (ebml, pos);
2311     } else {
2312       /* void'ify */
2313       guint64 my_pos = ebml->pos;
2314
2315       gst_ebml_write_seek (ebml, mux->duration_pos);
2316       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 8);
2317       gst_ebml_write_seek (ebml, my_pos);
2318     }
2319   }
2320   /* finish segment - this also writes element length */
2321   gst_ebml_write_master_finish (ebml, mux->segment_pos);
2322 }
2323
2324
2325 /**
2326  * gst_matroska_mux_best_pad:
2327  * @mux: #GstMatroskaMux
2328  * @popped: True if at least one buffer was popped from #GstCollectPads
2329  *
2330  * Find a pad with the oldest data 
2331  * (data from this pad should be written first).
2332  *
2333  * Returns: Selected pad.
2334  */
2335 static GstMatroskaPad *
2336 gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
2337 {
2338   GSList *collected;
2339   GstMatroskaPad *best = NULL;
2340
2341   *popped = FALSE;
2342   for (collected = mux->collect->data; collected;
2343       collected = g_slist_next (collected)) {
2344     GstMatroskaPad *collect_pad;
2345
2346     collect_pad = (GstMatroskaPad *) collected->data;
2347     /* fetch a new buffer if needed */
2348     if (collect_pad->buffer == NULL) {
2349       collect_pad->buffer = gst_collect_pads_pop (mux->collect,
2350           (GstCollectData *) collect_pad);
2351
2352       if (collect_pad->buffer != NULL)
2353         *popped = TRUE;
2354     }
2355
2356     /* if we have a buffer check if it is better then the current best one */
2357     if (collect_pad->buffer != NULL) {
2358       if (best == NULL || !GST_BUFFER_TIMESTAMP_IS_VALID (collect_pad->buffer)
2359           || (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)
2360               && GST_BUFFER_TIMESTAMP (collect_pad->buffer) <
2361               GST_BUFFER_TIMESTAMP (best->buffer))) {
2362         best = collect_pad;
2363       }
2364     }
2365   }
2366
2367   return best;
2368 }
2369
2370 /**
2371  * gst_matroska_mux_buffer_header:
2372  * @track: Track context.
2373  * @relative_timestamp: relative timestamp of the buffer
2374  * @flags: Buffer flags.
2375  *
2376  * Create a buffer containing buffer header.
2377  * 
2378  * Returns: New buffer.
2379  */
2380 static GstBuffer *
2381 gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
2382     gint16 relative_timestamp, int flags)
2383 {
2384   GstBuffer *hdr;
2385
2386   hdr = gst_buffer_new_and_alloc (4);
2387   /* track num - FIXME: what if num >= 0x80 (unlikely)? */
2388   GST_BUFFER_DATA (hdr)[0] = track->num | 0x80;
2389   /* time relative to clustertime */
2390   GST_WRITE_UINT16_BE (GST_BUFFER_DATA (hdr) + 1, relative_timestamp);
2391
2392   /* flags */
2393   GST_BUFFER_DATA (hdr)[3] = flags;
2394
2395   return hdr;
2396 }
2397
2398 #define DIRAC_PARSE_CODE_SEQUENCE_HEADER 0x00
2399 #define DIRAC_PARSE_CODE_END_OF_SEQUENCE 0x10
2400 #define DIRAC_PARSE_CODE_IS_PICTURE(x) ((x & 0x08) != 0)
2401
2402 static GstBuffer *
2403 gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
2404     GstMatroskaPad * collect_pad, GstBuffer * buf)
2405 {
2406   GstMatroskaTrackVideoContext *ctx =
2407       (GstMatroskaTrackVideoContext *) collect_pad->track;
2408   const guint8 *data = GST_BUFFER_DATA (buf);
2409   guint size = GST_BUFFER_SIZE (buf);
2410   guint8 parse_code;
2411   guint32 next_parse_offset;
2412   GstBuffer *ret = NULL;
2413   gboolean is_muxing_unit = FALSE;
2414
2415   if (GST_BUFFER_SIZE (buf) < 13) {
2416     gst_buffer_unref (buf);
2417     return ret;
2418   }
2419
2420   /* Check if this buffer contains a picture or end-of-sequence packet */
2421   while (size >= 13) {
2422     if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) {
2423       gst_buffer_unref (buf);
2424       return ret;
2425     }
2426
2427     parse_code = GST_READ_UINT8 (data + 4);
2428     if (parse_code == DIRAC_PARSE_CODE_SEQUENCE_HEADER) {
2429       if (ctx->dirac_unit) {
2430         gst_buffer_unref (ctx->dirac_unit);
2431         ctx->dirac_unit = NULL;
2432       }
2433     } else if (DIRAC_PARSE_CODE_IS_PICTURE (parse_code) ||
2434         parse_code == DIRAC_PARSE_CODE_END_OF_SEQUENCE) {
2435       is_muxing_unit = TRUE;
2436       break;
2437     }
2438
2439     next_parse_offset = GST_READ_UINT32_BE (data + 5);
2440
2441     if (G_UNLIKELY (next_parse_offset == 0))
2442       break;
2443
2444     data += next_parse_offset;
2445     size -= next_parse_offset;
2446   }
2447
2448   if (ctx->dirac_unit)
2449     ctx->dirac_unit = gst_buffer_join (ctx->dirac_unit, gst_buffer_ref (buf));
2450   else
2451     ctx->dirac_unit = gst_buffer_ref (buf);
2452
2453   if (is_muxing_unit) {
2454     ret = gst_buffer_make_metadata_writable (ctx->dirac_unit);
2455     ctx->dirac_unit = NULL;
2456     gst_buffer_copy_metadata (ret, buf,
2457         GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
2458         GST_BUFFER_COPY_CAPS);
2459     gst_buffer_unref (buf);
2460   } else {
2461     gst_buffer_unref (buf);
2462     ret = NULL;
2463   }
2464
2465   return ret;
2466 }
2467
2468 /**
2469  * gst_matroska_mux_write_data:
2470  * @mux: #GstMatroskaMux
2471  * @collect_pad: #GstMatroskaPad with the data
2472  *
2473  * Write collected data (called from gst_matroska_mux_collected).
2474  *
2475  * Returns: Result of the gst_pad_push issued to write the data.
2476  */
2477 static GstFlowReturn
2478 gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
2479 {
2480   GstEbmlWrite *ebml = mux->ebml_write;
2481   GstBuffer *buf, *hdr;
2482   guint64 blockgroup;
2483   gboolean write_duration;
2484   gint16 relative_timestamp;
2485   gint64 relative_timestamp64;
2486   guint64 block_duration;
2487   gboolean is_video_keyframe = FALSE;
2488
2489   /* write data */
2490   buf = collect_pad->buffer;
2491   collect_pad->buffer = NULL;
2492
2493   /* vorbis/theora headers are retrieved from caps and put in CodecPrivate */
2494   if (collect_pad->track->xiph_headers_to_skip > 0) {
2495     GST_LOG_OBJECT (collect_pad->collect.pad, "dropping streamheader buffer");
2496     gst_buffer_unref (buf);
2497     --collect_pad->track->xiph_headers_to_skip;
2498     return GST_FLOW_OK;
2499   }
2500
2501   /* for dirac we have to queue up everything up to a picture unit */
2502   if (collect_pad->track->codec_id != NULL &&
2503       strcmp (collect_pad->track->codec_id,
2504           GST_MATROSKA_CODEC_ID_VIDEO_DIRAC) == 0) {
2505     buf = gst_matroska_mux_handle_dirac_packet (mux, collect_pad, buf);
2506     if (!buf)
2507       return GST_FLOW_OK;
2508   }
2509
2510   /* hm, invalid timestamp (due to --to be fixed--- element upstream);
2511    * this would wreak havoc with time stored in matroska file */
2512   /* TODO: maybe calculate a timestamp by using the previous timestamp
2513    * and default duration */
2514   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2515     GST_WARNING_OBJECT (collect_pad->collect.pad,
2516         "Invalid buffer timestamp; dropping buffer");
2517     gst_buffer_unref (buf);
2518     return GST_FLOW_OK;
2519   }
2520
2521   /* set the timestamp for outgoing buffers */
2522   ebml->timestamp = GST_BUFFER_TIMESTAMP (buf);
2523
2524   if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
2525       !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
2526     GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT,
2527         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
2528     is_video_keyframe = TRUE;
2529   }
2530
2531   if (mux->cluster) {
2532     /* start a new cluster every two seconds or at keyframe */
2533     if (mux->cluster_time + GST_SECOND * 2 < GST_BUFFER_TIMESTAMP (buf)
2534         || is_video_keyframe) {
2535
2536       gst_ebml_write_master_finish (ebml, mux->cluster);
2537       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
2538       mux->cluster_pos = ebml->pos;
2539       gst_ebml_write_set_cache (ebml, 0x20);
2540       mux->cluster =
2541           gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2542       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2543           GST_BUFFER_TIMESTAMP (buf) / mux->time_scale);
2544       gst_ebml_write_flush_cache (ebml);
2545       mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2546       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
2547           mux->prev_cluster_size);
2548     }
2549   } else {
2550     /* first cluster */
2551
2552     mux->cluster_pos = ebml->pos;
2553     gst_ebml_write_set_cache (ebml, 0x20);
2554     mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2555     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2556         GST_BUFFER_TIMESTAMP (buf) / mux->time_scale);
2557     gst_ebml_write_flush_cache (ebml);
2558     mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2559   }
2560
2561   /* update duration of this track */
2562   if (GST_BUFFER_DURATION_IS_VALID (buf))
2563     collect_pad->duration += GST_BUFFER_DURATION (buf);
2564
2565   /* We currently write index entries for all video tracks or for the audio
2566    * track in a single-track audio file.  This could be improved by keeping the
2567    * index only for the *first* video track. */
2568
2569   /* TODO: index is useful for every track, should contain the number of
2570    * the block in the cluster which contains the timestamp, should also work
2571    * for files with multiple audio tracks.
2572    */
2573   if (is_video_keyframe ||
2574       ((collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO) &&
2575           (mux->num_streams == 1))) {
2576     gint last_idx = -1;
2577
2578     if (mux->min_index_interval != 0) {
2579       for (last_idx = mux->num_indexes - 1; last_idx >= 0; last_idx--) {
2580         if (mux->index[last_idx].track == collect_pad->track->num)
2581           break;
2582       }
2583     }
2584
2585     if (last_idx < 0 || mux->min_index_interval == 0 ||
2586         (GST_CLOCK_DIFF (mux->index[last_idx].time, GST_BUFFER_TIMESTAMP (buf))
2587             >= mux->min_index_interval)) {
2588       GstMatroskaIndex *idx;
2589
2590       if (mux->num_indexes % 32 == 0) {
2591         mux->index = g_renew (GstMatroskaIndex, mux->index,
2592             mux->num_indexes + 32);
2593       }
2594       idx = &mux->index[mux->num_indexes++];
2595
2596       idx->pos = mux->cluster_pos;
2597       idx->time = GST_BUFFER_TIMESTAMP (buf);
2598       idx->track = collect_pad->track->num;
2599     }
2600   }
2601
2602   /* Check if the duration differs from the default duration. */
2603   write_duration = FALSE;
2604   block_duration = GST_BUFFER_DURATION (buf);
2605   if (GST_BUFFER_DURATION_IS_VALID (buf)) {
2606     if (block_duration != collect_pad->track->default_duration) {
2607       write_duration = TRUE;
2608     }
2609   }
2610
2611   /* write the block, for doctype v2 use SimpleBlock if possible
2612    * one slice (*breath*).
2613    * FIXME: Need to do correct lacing! */
2614   relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time;
2615   if (relative_timestamp64 >= 0) {
2616     /* round the timestamp */
2617     relative_timestamp64 += mux->time_scale / 2;
2618   } else {
2619     /* round the timestamp */
2620     relative_timestamp64 -= mux->time_scale / 2;
2621   }
2622   relative_timestamp = relative_timestamp64 / (gint64) mux->time_scale;
2623   if (mux->doctype_version > 1 && !write_duration) {
2624     int flags =
2625         GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : 0x80;
2626
2627     hdr =
2628         gst_matroska_mux_create_buffer_header (collect_pad->track,
2629         relative_timestamp, flags);
2630     gst_ebml_write_set_cache (ebml, 0x40);
2631     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
2632         GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
2633     gst_ebml_write_buffer (ebml, hdr);
2634     gst_ebml_write_flush_cache (ebml);
2635     gst_ebml_write_buffer (ebml, buf);
2636
2637     return gst_ebml_last_write_result (ebml);
2638   } else {
2639     gst_ebml_write_set_cache (ebml, 0x40);
2640     /* write and call order slightly unnatural,
2641      * but avoids seek and minizes pushing */
2642     blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
2643     hdr =
2644         gst_matroska_mux_create_buffer_header (collect_pad->track,
2645         relative_timestamp, 0);
2646     if (write_duration) {
2647       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION,
2648           block_duration / mux->time_scale);
2649     }
2650     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
2651         GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
2652     gst_ebml_write_buffer (ebml, hdr);
2653     gst_ebml_write_master_finish_full (ebml, blockgroup, GST_BUFFER_SIZE (buf));
2654     gst_ebml_write_flush_cache (ebml);
2655     gst_ebml_write_buffer (ebml, buf);
2656     return gst_ebml_last_write_result (ebml);
2657   }
2658 }
2659
2660
2661 /**
2662  * gst_matroska_mux_collected:
2663  * @pads: #GstCollectPads
2664  * @uuser_data: #GstMatroskaMux
2665  *
2666  * Collectpads callback.
2667  *
2668  * Returns: #GstFlowReturn
2669  */
2670 static GstFlowReturn
2671 gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
2672 {
2673   GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
2674   GstMatroskaPad *best;
2675   gboolean popped;
2676   GstFlowReturn ret;
2677
2678   GST_DEBUG_OBJECT (mux, "Collected pads");
2679
2680   /* start with a header */
2681   if (mux->state == GST_MATROSKA_MUX_STATE_START) {
2682     if (mux->collect->data == NULL) {
2683       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
2684           ("No input streams configured"));
2685       return GST_FLOW_ERROR;
2686     }
2687     mux->state = GST_MATROSKA_MUX_STATE_HEADER;
2688     gst_matroska_mux_start (mux);
2689     mux->state = GST_MATROSKA_MUX_STATE_DATA;
2690   }
2691
2692   do {
2693     /* which stream to write from? */
2694     best = gst_matroska_mux_best_pad (mux, &popped);
2695
2696     /* if there is no best pad, we have reached EOS */
2697     if (best == NULL) {
2698       GST_DEBUG_OBJECT (mux, "No best pad finishing...");
2699       gst_matroska_mux_finish (mux);
2700       gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
2701       ret = GST_FLOW_UNEXPECTED;
2702       break;
2703     }
2704     GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
2705         GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
2706         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (best->buffer)),
2707         GST_TIME_ARGS (GST_BUFFER_DURATION (best->buffer)));
2708
2709     /* make note of first and last encountered timestamps, so we can calculate
2710      * the actual duration later when we send an updated header on eos */
2711     if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
2712       GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
2713       GstClockTime end_ts = start_ts;
2714
2715       if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
2716         end_ts += GST_BUFFER_DURATION (best->buffer);
2717       else if (best->track->default_duration)
2718         end_ts += best->track->default_duration;
2719
2720       if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
2721         best->end_ts = end_ts;
2722
2723       if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
2724               start_ts < best->start_ts))
2725         best->start_ts = start_ts;
2726     }
2727
2728     /* write one buffer */
2729     ret = gst_matroska_mux_write_data (mux, best);
2730   } while (ret == GST_FLOW_OK && !popped);
2731
2732   return ret;
2733 }
2734
2735
2736 /**
2737  * gst_matroska_mux_change_state:
2738  * @element: #GstMatroskaMux
2739  * @transition: State change transition.
2740  *
2741  * Change the muxer state.
2742  *
2743  * Returns: #GstStateChangeReturn
2744  */
2745 static GstStateChangeReturn
2746 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
2747 {
2748   GstStateChangeReturn ret;
2749   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
2750
2751   switch (transition) {
2752     case GST_STATE_CHANGE_NULL_TO_READY:
2753       break;
2754     case GST_STATE_CHANGE_READY_TO_PAUSED:
2755       gst_collect_pads_start (mux->collect);
2756       break;
2757     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2758       break;
2759     case GST_STATE_CHANGE_PAUSED_TO_READY:
2760       gst_collect_pads_stop (mux->collect);
2761       break;
2762     default:
2763       break;
2764   }
2765
2766   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2767
2768   switch (transition) {
2769     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2770       break;
2771     case GST_STATE_CHANGE_PAUSED_TO_READY:
2772       gst_matroska_mux_reset (GST_ELEMENT (mux));
2773       break;
2774     case GST_STATE_CHANGE_READY_TO_NULL:
2775       break;
2776     default:
2777       break;
2778   }
2779
2780   return ret;
2781 }
2782
2783 static void
2784 gst_matroska_mux_set_property (GObject * object,
2785     guint prop_id, const GValue * value, GParamSpec * pspec)
2786 {
2787   GstMatroskaMux *mux;
2788
2789   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
2790   mux = GST_MATROSKA_MUX (object);
2791
2792   switch (prop_id) {
2793     case ARG_WRITING_APP:
2794       if (!g_value_get_string (value)) {
2795         GST_WARNING_OBJECT (mux, "writing-app property can not be NULL");
2796         break;
2797       }
2798       g_free (mux->writing_app);
2799       mux->writing_app = g_value_dup_string (value);
2800       break;
2801     case ARG_DOCTYPE_VERSION:
2802       mux->doctype_version = g_value_get_int (value);
2803       break;
2804     case ARG_MIN_INDEX_INTERVAL:
2805       mux->min_index_interval = g_value_get_int64 (value);
2806       break;
2807     case ARG_IS_LIVE:
2808       mux->is_live = g_value_get_boolean (value);
2809       break;
2810     default:
2811       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2812       break;
2813   }
2814 }
2815
2816 static void
2817 gst_matroska_mux_get_property (GObject * object,
2818     guint prop_id, GValue * value, GParamSpec * pspec)
2819 {
2820   GstMatroskaMux *mux;
2821
2822   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
2823   mux = GST_MATROSKA_MUX (object);
2824
2825   switch (prop_id) {
2826     case ARG_WRITING_APP:
2827       g_value_set_string (value, mux->writing_app);
2828       break;
2829     case ARG_DOCTYPE_VERSION:
2830       g_value_set_int (value, mux->doctype_version);
2831       break;
2832     case ARG_MIN_INDEX_INTERVAL:
2833       g_value_set_int64 (value, mux->min_index_interval);
2834       break;
2835     case ARG_IS_LIVE:
2836       g_value_set_boolean (value, mux->is_live);
2837       break;
2838     default:
2839       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2840       break;
2841   }
2842 }