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