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