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