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