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