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