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