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