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       break;
786     }
787     case GST_EVENT_SEGMENT:{
788       const GstSegment *segment;
789
790       gst_event_parse_segment (event, &segment);
791       if (segment->format != GST_FORMAT_TIME) {
792         gst_event_unref (event);
793         event = NULL;
794       }
795       break;
796     }
797     case GST_EVENT_CUSTOM_DOWNSTREAM:{
798       const GstStructure *structure;
799
800       structure = gst_event_get_structure (event);
801       if (gst_structure_has_name (structure, "GstForceKeyUnit")) {
802         gst_event_replace (&mux->force_key_unit_event, NULL);
803         mux->force_key_unit_event = event;
804         event = NULL;
805       } else if (gst_structure_has_name (structure, "application/x-gst-dvd") &&
806           !strcmp ("dvd-spu-clut-change",
807               gst_structure_get_string (structure, "event"))) {
808         gchar name[16];
809         gint i, value;
810         guint clut[16];
811
812         GST_DEBUG_OBJECT (pad, "New DVD colour table received");
813         if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE) {
814           GST_DEBUG_OBJECT (pad, "... discarding");
815           break;
816         }
817         /* first transform event data into table form */
818         for (i = 0; i < 16; i++) {
819           g_snprintf (name, sizeof (name), "clut%02d", i);
820           if (!gst_structure_get_int (structure, name, &value)) {
821             GST_ERROR_OBJECT (mux, "dvd-spu-clut-change event did not "
822                 "contain %s field", name);
823             break;
824           }
825           clut[i] = value;
826         }
827
828         /* transform into private data for stream; text form */
829         gst_matroska_mux_build_vobsub_private (context, clut);
830       }
831       break;
832     }
833     default:
834       break;
835   }
836
837   /* now GstCollectPads2 can take care of the rest, e.g. EOS */
838   return ret;
839 }
840
841 static void
842 gst_matroska_mux_set_codec_id (GstMatroskaTrackContext * context,
843     const char *id)
844 {
845   g_assert (context && id);
846   if (context->codec_id)
847     g_free (context->codec_id);
848   context->codec_id = g_strdup (id);
849 }
850
851 /**
852  * gst_matroska_mux_video_pad_setcaps:
853  * @pad: Pad which got the caps.
854  * @caps: New caps.
855  *
856  * Setcaps function for video sink pad.
857  *
858  * Returns: #TRUE on success.
859  */
860 static gboolean
861 gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
862 {
863   GstMatroskaTrackContext *context = NULL;
864   GstMatroskaTrackVideoContext *videocontext;
865   GstMatroskaMux *mux;
866   GstMatroskaPad *collect_pad;
867   GstStructure *structure;
868   const gchar *mimetype;
869   const GValue *value = NULL;
870   GstBuffer *codec_buf = NULL;
871   gint width, height, pixel_width, pixel_height;
872   gint fps_d, fps_n;
873   gboolean interlaced = FALSE;
874
875   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
876
877   /* find context */
878   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
879   g_assert (collect_pad);
880   context = collect_pad->track;
881   g_assert (context);
882   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO);
883   videocontext = (GstMatroskaTrackVideoContext *) context;
884
885   /* gst -> matroska ID'ing */
886   structure = gst_caps_get_structure (caps, 0);
887
888   mimetype = gst_structure_get_name (structure);
889
890   if (gst_structure_get_boolean (structure, "interlaced", &interlaced)
891       && interlaced)
892     context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
893
894   if (!strcmp (mimetype, "video/x-theora")) {
895     /* we'll extract the details later from the theora identification header */
896     goto skip_details;
897   }
898
899   /* get general properties */
900   /* spec says it is mandatory */
901   if (!gst_structure_get_int (structure, "width", &width) ||
902       !gst_structure_get_int (structure, "height", &height))
903     goto refuse_caps;
904
905   videocontext->pixel_width = width;
906   videocontext->pixel_height = height;
907
908   /* set vp8 defaults or let user override it */
909   if (GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration_user == FALSE
910       && (!strcmp (mimetype, "video/x-vp8")))
911     GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration =
912         DEFAULT_PAD_FRAME_DURATION_VP8;
913
914   if (GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration
915       && gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)
916       && fps_n > 0) {
917     context->default_duration =
918         gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
919     GST_LOG_OBJECT (pad, "default duration = %" GST_TIME_FORMAT,
920         GST_TIME_ARGS (context->default_duration));
921   } else {
922     context->default_duration = 0;
923   }
924   if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
925           &pixel_width, &pixel_height)) {
926     if (pixel_width > pixel_height) {
927       videocontext->display_width = width * pixel_width / pixel_height;
928       videocontext->display_height = height;
929     } else if (pixel_width < pixel_height) {
930       videocontext->display_width = width;
931       videocontext->display_height = height * pixel_height / pixel_width;
932     } else {
933       videocontext->display_width = 0;
934       videocontext->display_height = 0;
935     }
936   } else {
937     videocontext->display_width = 0;
938     videocontext->display_height = 0;
939   }
940
941 skip_details:
942
943   videocontext->asr_mode = GST_MATROSKA_ASPECT_RATIO_MODE_FREE;
944   videocontext->fourcc = 0;
945
946   /* TODO: - check if we handle all codecs by the spec, i.e. codec private
947    *         data and other settings
948    *       - add new formats
949    */
950
951   /* extract codec_data, may turn out needed */
952   value = gst_structure_get_value (structure, "codec_data");
953   if (value)
954     codec_buf = (GstBuffer *) gst_value_get_buffer (value);
955
956   /* find type */
957   if (!strcmp (mimetype, "video/x-raw")) {
958     const gchar *fstr;
959     gst_matroska_mux_set_codec_id (context,
960         GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
961     fstr = gst_structure_get_string (structure, "format");
962     if (fstr && strlen (fstr) == 4)
963       videocontext->fourcc = GST_STR_FOURCC (fstr);
964   } else if (!strcmp (mimetype, "image/jpeg")) {
965     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
966   } else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
967       ||!strcmp (mimetype, "video/x-huffyuv")
968       || !strcmp (mimetype, "video/x-divx")
969       || !strcmp (mimetype, "video/x-dv")
970       || !strcmp (mimetype, "video/x-h263")
971       || !strcmp (mimetype, "video/x-msmpeg")
972       || !strcmp (mimetype, "video/x-wmv")
973       || !strcmp (mimetype, "image/jpeg")) {
974     gst_riff_strf_vids *bih;
975     gint size = sizeof (gst_riff_strf_vids);
976     guint32 fourcc = 0;
977
978     if (!strcmp (mimetype, "video/x-xvid"))
979       fourcc = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
980     else if (!strcmp (mimetype, "video/x-huffyuv"))
981       fourcc = GST_MAKE_FOURCC ('H', 'F', 'Y', 'U');
982     else if (!strcmp (mimetype, "video/x-dv"))
983       fourcc = GST_MAKE_FOURCC ('D', 'V', 'S', 'D');
984     else if (!strcmp (mimetype, "video/x-h263"))
985       fourcc = GST_MAKE_FOURCC ('H', '2', '6', '3');
986     else if (!strcmp (mimetype, "video/x-divx")) {
987       gint divxversion;
988
989       gst_structure_get_int (structure, "divxversion", &divxversion);
990       switch (divxversion) {
991         case 3:
992           fourcc = GST_MAKE_FOURCC ('D', 'I', 'V', '3');
993           break;
994         case 4:
995           fourcc = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
996           break;
997         case 5:
998           fourcc = GST_MAKE_FOURCC ('D', 'X', '5', '0');
999           break;
1000       }
1001     } else if (!strcmp (mimetype, "video/x-msmpeg")) {
1002       gint msmpegversion;
1003
1004       gst_structure_get_int (structure, "msmpegversion", &msmpegversion);
1005       switch (msmpegversion) {
1006         case 41:
1007           fourcc = GST_MAKE_FOURCC ('M', 'P', 'G', '4');
1008           break;
1009         case 42:
1010           fourcc = GST_MAKE_FOURCC ('M', 'P', '4', '2');
1011           break;
1012         case 43:
1013           goto msmpeg43;
1014           break;
1015       }
1016     } else if (!strcmp (mimetype, "video/x-wmv")) {
1017       gint wmvversion;
1018       const gchar *fstr;
1019
1020       fstr = gst_structure_get_string (structure, "format");
1021       if (fstr && strlen (fstr) == 4) {
1022         fourcc = GST_STR_FOURCC (fstr);
1023       } else if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) {
1024         if (wmvversion == 2) {
1025           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '2');
1026         } else if (wmvversion == 1) {
1027           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '1');
1028         } else if (wmvversion == 3) {
1029           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
1030         }
1031       }
1032     } else if (!strcmp (mimetype, "image/jpeg")) {
1033       fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
1034     }
1035
1036     if (!fourcc)
1037       goto refuse_caps;
1038
1039     bih = g_new0 (gst_riff_strf_vids, 1);
1040     GST_WRITE_UINT32_LE (&bih->size, size);
1041     GST_WRITE_UINT32_LE (&bih->width, videocontext->pixel_width);
1042     GST_WRITE_UINT32_LE (&bih->height, videocontext->pixel_height);
1043     GST_WRITE_UINT32_LE (&bih->compression, fourcc);
1044     GST_WRITE_UINT16_LE (&bih->planes, (guint16) 1);
1045     GST_WRITE_UINT16_LE (&bih->bit_cnt, (guint16) 24);
1046     GST_WRITE_UINT32_LE (&bih->image_size, videocontext->pixel_width *
1047         videocontext->pixel_height * 3);
1048
1049     /* process codec private/initialization data, if any */
1050     if (codec_buf) {
1051       size += gst_buffer_get_size (codec_buf);
1052       bih = g_realloc (bih, size);
1053       GST_WRITE_UINT32_LE (&bih->size, size);
1054       gst_buffer_extract (codec_buf, 0,
1055           (guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
1056     }
1057
1058     gst_matroska_mux_set_codec_id (context,
1059         GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
1060     gst_matroska_mux_free_codec_priv (context);
1061     context->codec_priv = (gpointer) bih;
1062     context->codec_priv_size = size;
1063   } else if (!strcmp (mimetype, "video/x-h264")) {
1064     gst_matroska_mux_set_codec_id (context,
1065         GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC);
1066     gst_matroska_mux_free_codec_priv (context);
1067     /* Create avcC header */
1068     if (codec_buf != NULL) {
1069       context->codec_priv_size = gst_buffer_get_size (codec_buf);
1070       context->codec_priv = g_malloc0 (context->codec_priv_size);
1071       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
1072     }
1073   } else if (!strcmp (mimetype, "video/x-theora")) {
1074     const GValue *streamheader;
1075
1076     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_THEORA);
1077
1078     gst_matroska_mux_free_codec_priv (context);
1079
1080     streamheader = gst_structure_get_value (structure, "streamheader");
1081     if (!theora_streamheader_to_codecdata (streamheader, context)) {
1082       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1083           ("theora stream headers missing or malformed"));
1084       goto refuse_caps;
1085     }
1086   } else if (!strcmp (mimetype, "video/x-dirac")) {
1087     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_DIRAC);
1088   } else if (!strcmp (mimetype, "video/x-vp8")) {
1089     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_VP8);
1090   } else if (!strcmp (mimetype, "video/mpeg")) {
1091     gint mpegversion;
1092
1093     gst_structure_get_int (structure, "mpegversion", &mpegversion);
1094     switch (mpegversion) {
1095       case 1:
1096         gst_matroska_mux_set_codec_id (context,
1097             GST_MATROSKA_CODEC_ID_VIDEO_MPEG1);
1098         break;
1099       case 2:
1100         gst_matroska_mux_set_codec_id (context,
1101             GST_MATROSKA_CODEC_ID_VIDEO_MPEG2);
1102         break;
1103       case 4:
1104         gst_matroska_mux_set_codec_id (context,
1105             GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP);
1106         break;
1107       default:
1108         goto refuse_caps;
1109     }
1110
1111     /* global headers may be in codec data */
1112     if (codec_buf != NULL) {
1113       gst_matroska_mux_free_codec_priv (context);
1114       context->codec_priv_size = gst_buffer_get_size (codec_buf);
1115       context->codec_priv = g_malloc0 (context->codec_priv_size);
1116       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
1117     }
1118   } else if (!strcmp (mimetype, "video/x-msmpeg")) {
1119   msmpeg43:
1120     /* can only make it here if preceding case verified it was version 3 */
1121     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3);
1122   } else if (!strcmp (mimetype, "video/x-pn-realvideo")) {
1123     gint rmversion;
1124     const GValue *mdpr_data;
1125
1126     gst_structure_get_int (structure, "rmversion", &rmversion);
1127     switch (rmversion) {
1128       case 1:
1129         gst_matroska_mux_set_codec_id (context,
1130             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
1131         break;
1132       case 2:
1133         gst_matroska_mux_set_codec_id (context,
1134             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
1135         break;
1136       case 3:
1137         gst_matroska_mux_set_codec_id (context,
1138             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
1139         break;
1140       case 4:
1141         gst_matroska_mux_set_codec_id (context,
1142             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
1143         break;
1144       default:
1145         goto refuse_caps;
1146     }
1147
1148     mdpr_data = gst_structure_get_value (structure, "mdpr_data");
1149     if (mdpr_data != NULL) {
1150       guint8 *priv_data = NULL;
1151       guint priv_data_size = 0;
1152
1153       GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
1154
1155       priv_data_size = gst_buffer_get_size (codec_data_buf);
1156       priv_data = g_malloc0 (priv_data_size);
1157
1158       gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
1159
1160       gst_matroska_mux_free_codec_priv (context);
1161       context->codec_priv = priv_data;
1162       context->codec_priv_size = priv_data_size;
1163     }
1164   }
1165
1166   return TRUE;
1167
1168   /* ERRORS */
1169 refuse_caps:
1170   {
1171     GST_WARNING_OBJECT (mux, "pad %s refused caps %" GST_PTR_FORMAT,
1172         GST_PAD_NAME (pad), caps);
1173     return FALSE;
1174   }
1175 }
1176
1177 /* N > 0 to expect a particular number of headers, negative if the
1178    number of headers is variable */
1179 static gboolean
1180 xiphN_streamheader_to_codecdata (const GValue * streamheader,
1181     GstMatroskaTrackContext * context, GstBuffer ** p_buf0, int N)
1182 {
1183   GstBuffer **buf = NULL;
1184   GArray *bufarr;
1185   guint8 *priv_data;
1186   guint bufi, i, offset, priv_data_size;
1187
1188   if (streamheader == NULL)
1189     goto no_stream_headers;
1190
1191   if (G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY)
1192     goto wrong_type;
1193
1194   bufarr = g_value_peek_pointer (streamheader);
1195   if (bufarr->len <= 0 || bufarr->len > 255)    /* at least one header, and count stored in a byte */
1196     goto wrong_count;
1197   if (N > 0 && bufarr->len != N)
1198     goto wrong_count;
1199
1200   context->xiph_headers_to_skip = bufarr->len;
1201
1202   buf = (GstBuffer **) g_malloc0 (sizeof (GstBuffer *) * bufarr->len);
1203   for (i = 0; i < bufarr->len; i++) {
1204     GValue *bufval = &g_array_index (bufarr, GValue, i);
1205
1206     if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1207       g_free (buf);
1208       goto wrong_content_type;
1209     }
1210
1211     buf[i] = g_value_peek_pointer (bufval);
1212   }
1213
1214   priv_data_size = 1;
1215   if (bufarr->len > 0) {
1216     for (i = 0; i < bufarr->len - 1; i++) {
1217       priv_data_size += gst_buffer_get_size (buf[i]) / 0xff + 1;
1218     }
1219   }
1220
1221   for (i = 0; i < bufarr->len; ++i) {
1222     priv_data_size += gst_buffer_get_size (buf[i]);
1223   }
1224
1225   priv_data = g_malloc0 (priv_data_size);
1226
1227   priv_data[0] = bufarr->len - 1;
1228   offset = 1;
1229
1230   if (bufarr->len > 0) {
1231     for (bufi = 0; bufi < bufarr->len - 1; bufi++) {
1232       for (i = 0; i < gst_buffer_get_size (buf[bufi]) / 0xff; ++i) {
1233         priv_data[offset++] = 0xff;
1234       }
1235       priv_data[offset++] = gst_buffer_get_size (buf[bufi]) % 0xff;
1236     }
1237   }
1238
1239   for (i = 0; i < bufarr->len; ++i) {
1240     gst_buffer_extract (buf[i], 0, priv_data + offset, -1);
1241     offset += gst_buffer_get_size (buf[i]);
1242   }
1243
1244   gst_matroska_mux_free_codec_priv (context);
1245   context->codec_priv = priv_data;
1246   context->codec_priv_size = priv_data_size;
1247
1248   if (p_buf0)
1249     *p_buf0 = gst_buffer_ref (buf[0]);
1250
1251   g_free (buf);
1252
1253   return TRUE;
1254
1255 /* ERRORS */
1256 no_stream_headers:
1257   {
1258     GST_WARNING ("required streamheaders missing in sink caps!");
1259     return FALSE;
1260   }
1261 wrong_type:
1262   {
1263     GST_WARNING ("streamheaders are not a GST_TYPE_ARRAY, but a %s",
1264         G_VALUE_TYPE_NAME (streamheader));
1265     return FALSE;
1266   }
1267 wrong_count:
1268   {
1269     GST_WARNING ("got %u streamheaders, not %d as expected", bufarr->len, N);
1270     return FALSE;
1271   }
1272 wrong_content_type:
1273   {
1274     GST_WARNING ("streamheaders array does not contain GstBuffers");
1275     return FALSE;
1276   }
1277 }
1278
1279 static gboolean
1280 vorbis_streamheader_to_codecdata (const GValue * streamheader,
1281     GstMatroskaTrackContext * context)
1282 {
1283   GstBuffer *buf0 = NULL;
1284
1285   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
1286     return FALSE;
1287
1288   if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 4) {
1289     GST_WARNING ("First vorbis header too small, ignoring");
1290   } else {
1291     if (gst_buffer_memcmp (buf0, 1, "vorbis", 6) == 0) {
1292       GstMatroskaTrackAudioContext *audiocontext;
1293       guint8 *data, *hdr;
1294
1295       data = gst_buffer_map (buf0, NULL, NULL, GST_MAP_READ);
1296       hdr = data + 1 + 6 + 4;
1297       audiocontext = (GstMatroskaTrackAudioContext *) context;
1298       audiocontext->channels = GST_READ_UINT8 (hdr);
1299       audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1);
1300       gst_buffer_unmap (buf0, data, -1);
1301     }
1302   }
1303
1304   if (buf0)
1305     gst_buffer_unref (buf0);
1306
1307   return TRUE;
1308 }
1309
1310 static gboolean
1311 theora_streamheader_to_codecdata (const GValue * streamheader,
1312     GstMatroskaTrackContext * context)
1313 {
1314   GstBuffer *buf0 = NULL;
1315
1316   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
1317     return FALSE;
1318
1319   if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 26) {
1320     GST_WARNING ("First theora header too small, ignoring");
1321   } else if (gst_buffer_memcmp (buf0, 0, "\200theora\003\002", 9) != 0) {
1322     GST_WARNING ("First header not a theora identification header, ignoring");
1323   } else {
1324     GstMatroskaTrackVideoContext *videocontext;
1325     guint fps_num, fps_denom, par_num, par_denom;
1326     guint8 *data, *hdr;
1327
1328     data = gst_buffer_map (buf0, NULL, NULL, GST_MAP_READ);
1329     hdr = data + 1 + 6 + 3 + 2 + 2;
1330
1331     videocontext = (GstMatroskaTrackVideoContext *) context;
1332     videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8;
1333     videocontext->pixel_height = GST_READ_UINT32_BE (hdr + 3) >> 8;
1334     hdr += 3 + 3 + 1 + 1;
1335     fps_num = GST_READ_UINT32_BE (hdr);
1336     fps_denom = GST_READ_UINT32_BE (hdr + 4);
1337     context->default_duration = gst_util_uint64_scale_int (GST_SECOND,
1338         fps_denom, fps_num);
1339     hdr += 4 + 4;
1340     par_num = GST_READ_UINT32_BE (hdr) >> 8;
1341     par_denom = GST_READ_UINT32_BE (hdr + 3) >> 8;
1342     if (par_num > 0 && par_num > 0) {
1343       if (par_num > par_denom) {
1344         videocontext->display_width =
1345             videocontext->pixel_width * par_num / par_denom;
1346         videocontext->display_height = videocontext->pixel_height;
1347       } else if (par_num < par_denom) {
1348         videocontext->display_width = videocontext->pixel_width;
1349         videocontext->display_height =
1350             videocontext->pixel_height * par_denom / par_num;
1351       } else {
1352         videocontext->display_width = 0;
1353         videocontext->display_height = 0;
1354       }
1355     } else {
1356       videocontext->display_width = 0;
1357       videocontext->display_height = 0;
1358     }
1359     hdr += 3 + 3;
1360
1361     gst_buffer_unmap (buf0, data, -1);
1362   }
1363
1364   if (buf0)
1365     gst_buffer_unref (buf0);
1366
1367   return TRUE;
1368 }
1369
1370 static gboolean
1371 kate_streamheader_to_codecdata (const GValue * streamheader,
1372     GstMatroskaTrackContext * context)
1373 {
1374   GstBuffer *buf0 = NULL;
1375
1376   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1))
1377     return FALSE;
1378
1379   if (buf0 == NULL || gst_buffer_get_size (buf0) < 64) {        /* Kate ID header is 64 bytes */
1380     GST_WARNING ("First kate header too small, ignoring");
1381   } else if (gst_buffer_memcmp (buf0, 0, "\200kate\0\0\0", 8) != 0) {
1382     GST_WARNING ("First header not a kate identification header, ignoring");
1383   }
1384
1385   if (buf0)
1386     gst_buffer_unref (buf0);
1387
1388   return TRUE;
1389 }
1390
1391 static gboolean
1392 flac_streamheader_to_codecdata (const GValue * streamheader,
1393     GstMatroskaTrackContext * context)
1394 {
1395   GArray *bufarr;
1396   gint i;
1397   GValue *bufval;
1398   GstBuffer *buffer;
1399
1400   if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
1401     GST_WARNING ("No or invalid streamheader field in the caps");
1402     return FALSE;
1403   }
1404
1405   bufarr = g_value_peek_pointer (streamheader);
1406   if (bufarr->len < 2) {
1407     GST_WARNING ("Too few headers in streamheader field");
1408     return FALSE;
1409   }
1410
1411   context->xiph_headers_to_skip = bufarr->len + 1;
1412
1413   bufval = &g_array_index (bufarr, GValue, 0);
1414   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1415     GST_WARNING ("streamheaders array does not contain GstBuffers");
1416     return FALSE;
1417   }
1418
1419   buffer = g_value_peek_pointer (bufval);
1420
1421   /* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */
1422   if (gst_buffer_get_size (buffer) < 9 + 4 + 4 + 34
1423       || gst_buffer_memcmp (buffer, 1, "FLAC", 4) != 0
1424       || gst_buffer_memcmp (buffer, 9, "fLaC", 4) != 0) {
1425     GST_WARNING ("Invalid streamheader for FLAC");
1426     return FALSE;
1427   }
1428
1429   gst_matroska_mux_free_codec_priv (context);
1430   context->codec_priv_size = gst_buffer_get_size (buffer) - 9;
1431   context->codec_priv = g_malloc (context->codec_priv_size);
1432   gst_buffer_extract (buffer, 9, context->codec_priv, -1);
1433
1434   for (i = 1; i < bufarr->len; i++) {
1435     guint old_size;
1436     bufval = &g_array_index (bufarr, GValue, i);
1437
1438     if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1439       gst_matroska_mux_free_codec_priv (context);
1440       GST_WARNING ("streamheaders array does not contain GstBuffers");
1441       return FALSE;
1442     }
1443
1444     buffer = g_value_peek_pointer (bufval);
1445
1446     old_size = context->codec_priv_size;
1447     context->codec_priv_size += gst_buffer_get_size (buffer);
1448
1449     context->codec_priv = g_realloc (context->codec_priv,
1450         context->codec_priv_size);
1451     gst_buffer_extract (buffer, 0,
1452         (guint8 *) context->codec_priv + old_size, -1);
1453   }
1454
1455   return TRUE;
1456 }
1457
1458 static gboolean
1459 speex_streamheader_to_codecdata (const GValue * streamheader,
1460     GstMatroskaTrackContext * context)
1461 {
1462   GArray *bufarr;
1463   GValue *bufval;
1464   GstBuffer *buffer;
1465   guint old_size;
1466
1467   if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
1468     GST_WARNING ("No or invalid streamheader field in the caps");
1469     return FALSE;
1470   }
1471
1472   bufarr = g_value_peek_pointer (streamheader);
1473   if (bufarr->len != 2) {
1474     GST_WARNING ("Too few headers in streamheader field");
1475     return FALSE;
1476   }
1477
1478   context->xiph_headers_to_skip = bufarr->len + 1;
1479
1480   bufval = &g_array_index (bufarr, GValue, 0);
1481   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1482     GST_WARNING ("streamheaders array does not contain GstBuffers");
1483     return FALSE;
1484   }
1485
1486   buffer = g_value_peek_pointer (bufval);
1487
1488   if (gst_buffer_get_size (buffer) < 80
1489       || gst_buffer_memcmp (buffer, 0, "Speex   ", 8) != 0) {
1490     GST_WARNING ("Invalid streamheader for Speex");
1491     return FALSE;
1492   }
1493
1494   gst_matroska_mux_free_codec_priv (context);
1495   context->codec_priv_size = gst_buffer_get_size (buffer);
1496   context->codec_priv = g_malloc (context->codec_priv_size);
1497   gst_buffer_extract (buffer, 0, context->codec_priv, -1);
1498
1499   bufval = &g_array_index (bufarr, GValue, 1);
1500
1501   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1502     gst_matroska_mux_free_codec_priv (context);
1503     GST_WARNING ("streamheaders array does not contain GstBuffers");
1504     return FALSE;
1505   }
1506
1507   buffer = g_value_peek_pointer (bufval);
1508
1509   old_size = context->codec_priv_size;
1510   context->codec_priv_size += gst_buffer_get_size (buffer);
1511   context->codec_priv = g_realloc (context->codec_priv,
1512       context->codec_priv_size);
1513   gst_buffer_extract (buffer, 0, (guint8 *) context->codec_priv + old_size, -1);
1514
1515   return TRUE;
1516 }
1517
1518 static const gchar *
1519 aac_codec_data_to_codec_id (GstBuffer * buf)
1520 {
1521   const gchar *result;
1522   guint8 profile;
1523
1524   /* default to MAIN */
1525   profile = 1;
1526
1527   if (gst_buffer_get_size (buf) >= 2) {
1528     gst_buffer_extract (buf, 0, &profile, 1);
1529     profile >>= 3;
1530   }
1531
1532   switch (profile) {
1533     case 1:
1534       result = "MAIN";
1535       break;
1536     case 2:
1537       result = "LC";
1538       break;
1539     case 3:
1540       result = "SSR";
1541       break;
1542     case 4:
1543       result = "LTP";
1544       break;
1545     default:
1546       GST_WARNING ("unknown AAC profile, defaulting to MAIN");
1547       result = "MAIN";
1548       break;
1549   }
1550
1551   return result;
1552 }
1553
1554 /**
1555  * gst_matroska_mux_audio_pad_setcaps:
1556  * @pad: Pad which got the caps.
1557  * @caps: New caps.
1558  *
1559  * Setcaps function for audio sink pad.
1560  *
1561  * Returns: #TRUE on success.
1562  */
1563 static gboolean
1564 gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
1565 {
1566   GstMatroskaTrackContext *context = NULL;
1567   GstMatroskaTrackAudioContext *audiocontext;
1568   GstMatroskaMux *mux;
1569   GstMatroskaPad *collect_pad;
1570   const gchar *mimetype;
1571   gint samplerate = 0, channels = 0;
1572   GstStructure *structure;
1573   const GValue *codec_data = NULL;
1574   GstBuffer *buf = NULL;
1575   const gchar *stream_format = NULL;
1576
1577   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
1578
1579   /* find context */
1580   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
1581   g_assert (collect_pad);
1582   context = collect_pad->track;
1583   g_assert (context);
1584   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO);
1585   audiocontext = (GstMatroskaTrackAudioContext *) context;
1586
1587   structure = gst_caps_get_structure (caps, 0);
1588   mimetype = gst_structure_get_name (structure);
1589
1590   /* general setup */
1591   gst_structure_get_int (structure, "rate", &samplerate);
1592   gst_structure_get_int (structure, "channels", &channels);
1593
1594   audiocontext->samplerate = samplerate;
1595   audiocontext->channels = channels;
1596   audiocontext->bitdepth = 0;
1597   context->default_duration = 0;
1598
1599   codec_data = gst_structure_get_value (structure, "codec_data");
1600   if (codec_data)
1601     buf = gst_value_get_buffer (codec_data);
1602
1603   /* TODO: - check if we handle all codecs by the spec, i.e. codec private
1604    *         data and other settings
1605    *       - add new formats
1606    */
1607
1608   if (!strcmp (mimetype, "audio/mpeg")) {
1609     gint mpegversion = 0;
1610
1611     gst_structure_get_int (structure, "mpegversion", &mpegversion);
1612     switch (mpegversion) {
1613       case 1:{
1614         gint layer;
1615         gint version = 1;
1616         gint spf;
1617
1618         gst_structure_get_int (structure, "layer", &layer);
1619
1620         if (!gst_structure_get_int (structure, "mpegaudioversion", &version)) {
1621           GST_WARNING_OBJECT (mux,
1622               "Unable to determine MPEG audio version, assuming 1");
1623           version = 1;
1624         }
1625
1626         if (layer == 1)
1627           spf = 384;
1628         else if (layer == 2)
1629           spf = 1152;
1630         else if (version == 2)
1631           spf = 576;
1632         else
1633           spf = 1152;
1634
1635         context->default_duration =
1636             gst_util_uint64_scale (GST_SECOND, spf, audiocontext->samplerate);
1637
1638         switch (layer) {
1639           case 1:
1640             gst_matroska_mux_set_codec_id (context,
1641                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1);
1642             break;
1643           case 2:
1644             gst_matroska_mux_set_codec_id (context,
1645                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2);
1646             break;
1647           case 3:
1648             gst_matroska_mux_set_codec_id (context,
1649                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3);
1650             break;
1651           default:
1652             goto refuse_caps;
1653         }
1654         break;
1655       }
1656       case 2:
1657       case 4:
1658         stream_format = gst_structure_get_string (structure, "stream-format");
1659         /* check this is raw aac */
1660         if (stream_format) {
1661           if (strcmp (stream_format, "raw") != 0) {
1662             GST_WARNING_OBJECT (mux, "AAC stream-format must be 'raw', not %s",
1663                 stream_format);
1664           }
1665         } else {
1666           GST_WARNING_OBJECT (mux, "AAC stream-format not specified, "
1667               "assuming 'raw'");
1668         }
1669
1670         if (buf) {
1671           if (mpegversion == 2)
1672             context->codec_id =
1673                 g_strdup_printf (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2 "%s",
1674                 aac_codec_data_to_codec_id (buf));
1675           else if (mpegversion == 4)
1676             context->codec_id =
1677                 g_strdup_printf (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4 "%s",
1678                 aac_codec_data_to_codec_id (buf));
1679           else
1680             g_assert_not_reached ();
1681         } else {
1682           GST_DEBUG_OBJECT (mux, "no AAC codec_data; not packetized");
1683           goto refuse_caps;
1684         }
1685         break;
1686       default:
1687         goto refuse_caps;
1688     }
1689   } else if (!strcmp (mimetype, "audio/x-raw")) {
1690     GstAudioInfo info;
1691
1692     gst_audio_info_init (&info);
1693     if (!gst_audio_info_from_caps (&info, caps)) {
1694       GST_DEBUG_OBJECT (mux,
1695           "broken caps, rejected by gst_audio_info_from_caps");
1696       goto refuse_caps;
1697     }
1698
1699     switch (GST_AUDIO_INFO_FORMAT (&info)) {
1700       case GST_AUDIO_FORMAT_U8:
1701       case GST_AUDIO_FORMAT_S16BE:
1702       case GST_AUDIO_FORMAT_S16LE:
1703       case GST_AUDIO_FORMAT_S24BE:
1704       case GST_AUDIO_FORMAT_S24LE:
1705       case GST_AUDIO_FORMAT_S32BE:
1706       case GST_AUDIO_FORMAT_S32LE:
1707         if (GST_AUDIO_INFO_WIDTH (&info) != GST_AUDIO_INFO_DEPTH (&info)) {
1708           GST_DEBUG_OBJECT (mux, "width must be same as depth!");
1709           goto refuse_caps;
1710         }
1711         if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info))
1712           gst_matroska_mux_set_codec_id (context,
1713               GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
1714         else
1715           gst_matroska_mux_set_codec_id (context,
1716               GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
1717         break;
1718       case GST_AUDIO_FORMAT_F32LE:
1719       case GST_AUDIO_FORMAT_F64LE:
1720         gst_matroska_mux_set_codec_id (context,
1721             GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
1722         break;
1723
1724       default:
1725         GST_DEBUG_OBJECT (mux, "wrong format in raw audio caps");
1726         goto refuse_caps;
1727     }
1728
1729     audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
1730   } else if (!strcmp (mimetype, "audio/x-vorbis")) {
1731     const GValue *streamheader;
1732
1733     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS);
1734
1735     gst_matroska_mux_free_codec_priv (context);
1736
1737     streamheader = gst_structure_get_value (structure, "streamheader");
1738     if (!vorbis_streamheader_to_codecdata (streamheader, context)) {
1739       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1740           ("vorbis stream headers missing or malformed"));
1741       goto refuse_caps;
1742     }
1743   } else if (!strcmp (mimetype, "audio/x-flac")) {
1744     const GValue *streamheader;
1745
1746     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_FLAC);
1747
1748     gst_matroska_mux_free_codec_priv (context);
1749
1750     streamheader = gst_structure_get_value (structure, "streamheader");
1751     if (!flac_streamheader_to_codecdata (streamheader, context)) {
1752       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1753           ("flac stream headers missing or malformed"));
1754       goto refuse_caps;
1755     }
1756   } else if (!strcmp (mimetype, "audio/x-speex")) {
1757     const GValue *streamheader;
1758
1759     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_SPEEX);
1760     gst_matroska_mux_free_codec_priv (context);
1761
1762     streamheader = gst_structure_get_value (structure, "streamheader");
1763     if (!speex_streamheader_to_codecdata (streamheader, context)) {
1764       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1765           ("speex stream headers missing or malformed"));
1766       goto refuse_caps;
1767     }
1768   } else if (!strcmp (mimetype, "audio/x-ac3")) {
1769     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_AC3);
1770   } else if (!strcmp (mimetype, "audio/x-eac3")) {
1771     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_EAC3);
1772   } else if (!strcmp (mimetype, "audio/x-dts")) {
1773     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_DTS);
1774   } else if (!strcmp (mimetype, "audio/x-tta")) {
1775     gint width;
1776
1777     /* TTA frame duration */
1778     context->default_duration = 1.04489795918367346939 * GST_SECOND;
1779
1780     gst_structure_get_int (structure, "width", &width);
1781     audiocontext->bitdepth = width;
1782     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_TTA);
1783
1784   } else if (!strcmp (mimetype, "audio/x-pn-realaudio")) {
1785     gint raversion;
1786     const GValue *mdpr_data;
1787
1788     gst_structure_get_int (structure, "raversion", &raversion);
1789     switch (raversion) {
1790       case 1:
1791         gst_matroska_mux_set_codec_id (context,
1792             GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
1793         break;
1794       case 2:
1795         gst_matroska_mux_set_codec_id (context,
1796             GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
1797         break;
1798       case 8:
1799         gst_matroska_mux_set_codec_id (context,
1800             GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
1801         break;
1802       default:
1803         goto refuse_caps;
1804     }
1805
1806     mdpr_data = gst_structure_get_value (structure, "mdpr_data");
1807     if (mdpr_data != NULL) {
1808       guint8 *priv_data = NULL;
1809       guint priv_data_size = 0;
1810
1811       GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
1812
1813       priv_data_size = gst_buffer_get_size (codec_data_buf);
1814       priv_data = g_malloc0 (priv_data_size);
1815
1816       gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
1817
1818       gst_matroska_mux_free_codec_priv (context);
1819
1820       context->codec_priv = priv_data;
1821       context->codec_priv_size = priv_data_size;
1822     }
1823
1824   } else if (!strcmp (mimetype, "audio/x-wma")
1825       || !strcmp (mimetype, "audio/x-alaw")
1826       || !strcmp (mimetype, "audio/x-mulaw")) {
1827     guint8 *codec_priv;
1828     guint codec_priv_size;
1829     guint16 format = 0;
1830     gint block_align;
1831     gint bitrate;
1832
1833     if (samplerate == 0 || channels == 0) {
1834       GST_WARNING_OBJECT (mux, "Missing channels/samplerate on caps");
1835       goto refuse_caps;
1836     }
1837
1838     if (!strcmp (mimetype, "audio/x-wma")) {
1839       gint wmaversion;
1840       gint depth;
1841
1842       if (!gst_structure_get_int (structure, "wmaversion", &wmaversion)
1843           || !gst_structure_get_int (structure, "block_align", &block_align)
1844           || !gst_structure_get_int (structure, "bitrate", &bitrate)) {
1845         GST_WARNING_OBJECT (mux, "Missing wmaversion/block_align/bitrate"
1846             " on WMA caps");
1847         goto refuse_caps;
1848       }
1849
1850       switch (wmaversion) {
1851         case 1:
1852           format = GST_RIFF_WAVE_FORMAT_WMAV1;
1853           break;
1854         case 2:
1855           format = GST_RIFF_WAVE_FORMAT_WMAV2;
1856           break;
1857         case 3:
1858           format = GST_RIFF_WAVE_FORMAT_WMAV3;
1859           break;
1860         default:
1861           GST_WARNING_OBJECT (mux, "Unexpected WMA version: %d", wmaversion);
1862           goto refuse_caps;
1863       }
1864
1865       if (gst_structure_get_int (structure, "depth", &depth))
1866         audiocontext->bitdepth = depth;
1867     } else if (!strcmp (mimetype, "audio/x-alaw")
1868         || !strcmp (mimetype, "audio/x-mulaw")) {
1869       audiocontext->bitdepth = 8;
1870       if (!strcmp (mimetype, "audio/x-alaw"))
1871         format = GST_RIFF_WAVE_FORMAT_ALAW;
1872       else
1873         format = GST_RIFF_WAVE_FORMAT_MULAW;
1874
1875       block_align = channels;
1876       bitrate = block_align * samplerate;
1877     }
1878     g_assert (format != 0);
1879
1880     codec_priv_size = WAVEFORMATEX_SIZE;
1881     if (buf)
1882       codec_priv_size += gst_buffer_get_size (buf);
1883
1884     /* serialize waveformatex structure */
1885     codec_priv = g_malloc0 (codec_priv_size);
1886     GST_WRITE_UINT16_LE (codec_priv, format);
1887     GST_WRITE_UINT16_LE (codec_priv + 2, channels);
1888     GST_WRITE_UINT32_LE (codec_priv + 4, samplerate);
1889     GST_WRITE_UINT32_LE (codec_priv + 8, bitrate / 8);
1890     GST_WRITE_UINT16_LE (codec_priv + 12, block_align);
1891     GST_WRITE_UINT16_LE (codec_priv + 14, 0);
1892     if (buf)
1893       GST_WRITE_UINT16_LE (codec_priv + 16, gst_buffer_get_size (buf));
1894     else
1895       GST_WRITE_UINT16_LE (codec_priv + 16, 0);
1896
1897     /* process codec private/initialization data, if any */
1898     if (buf) {
1899       gst_buffer_extract (buf, 0,
1900           (guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
1901     }
1902
1903     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_ACM);
1904     gst_matroska_mux_free_codec_priv (context);
1905     context->codec_priv = (gpointer) codec_priv;
1906     context->codec_priv_size = codec_priv_size;
1907   }
1908
1909   return TRUE;
1910
1911   /* ERRORS */
1912 refuse_caps:
1913   {
1914     GST_WARNING_OBJECT (mux, "pad %s refused caps %" GST_PTR_FORMAT,
1915         GST_PAD_NAME (pad), caps);
1916     return FALSE;
1917   }
1918 }
1919
1920 /* we probably don't have the data at start,
1921  * so have to reserve (a maximum) space to write this at the end.
1922  * bit spacy, but some formats can hold quite some */
1923 #define SUBTITLE_MAX_CODEC_PRIVATE   2048       /* must be > 128 */
1924
1925 /**
1926  * gst_matroska_mux_subtitle_pad_setcaps:
1927  * @pad: Pad which got the caps.
1928  * @caps: New caps.
1929  *
1930  * Setcaps function for subtitle sink pad.
1931  *
1932  * Returns: #TRUE on success.
1933  */
1934 static gboolean
1935 gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
1936 {
1937   /* There is now (at least) one such alement (kateenc), and I'm going
1938      to handle it here and claim it works when it can be piped back
1939      through GStreamer and VLC */
1940
1941   GstMatroskaTrackContext *context = NULL;
1942   GstMatroskaTrackSubtitleContext *scontext;
1943   GstMatroskaMux *mux;
1944   GstMatroskaPad *collect_pad;
1945   const gchar *mimetype;
1946   GstStructure *structure;
1947   const GValue *value = NULL;
1948   GstBuffer *buf = NULL;
1949   gchar *id = NULL;
1950   gboolean ret = TRUE;
1951
1952   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
1953
1954   /* find context */
1955   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
1956   g_assert (collect_pad);
1957   context = collect_pad->track;
1958   g_assert (context);
1959   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE);
1960   scontext = (GstMatroskaTrackSubtitleContext *) context;
1961
1962   structure = gst_caps_get_structure (caps, 0);
1963   mimetype = gst_structure_get_name (structure);
1964
1965   /* keep track of default set in request_pad */
1966   id = context->codec_id;
1967
1968   /* general setup */
1969   scontext->check_utf8 = 1;
1970   scontext->invalid_utf8 = 0;
1971   context->default_duration = 0;
1972
1973   if (!strcmp (mimetype, "subtitle/x-kate")) {
1974     const GValue *streamheader;
1975
1976     gst_matroska_mux_set_codec_id (context,
1977         GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
1978
1979     gst_matroska_mux_free_codec_priv (context);
1980
1981     streamheader = gst_structure_get_value (structure, "streamheader");
1982     if (!kate_streamheader_to_codecdata (streamheader, context)) {
1983       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1984           ("kate stream headers missing or malformed"));
1985       ret = FALSE;
1986       goto exit;
1987     }
1988   } else if (!strcmp (mimetype, "text/plain")) {
1989     gst_matroska_mux_set_codec_id (context,
1990         GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8);
1991   } else if (!strcmp (mimetype, "application/x-ssa")) {
1992     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_SSA);
1993   } else if (!strcmp (mimetype, "application/x-ass")) {
1994     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_ASS);
1995   } else if (!strcmp (mimetype, "application/x-usf")) {
1996     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_USF);
1997   } else if (!strcmp (mimetype, "video/x-dvd-subpicture")) {
1998     gst_matroska_mux_set_codec_id (context,
1999         GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB);
2000   } else {
2001     id = NULL;
2002     ret = FALSE;
2003     goto exit;
2004   }
2005
2006   /* maybe some private data, e.g. vobsub */
2007   value = gst_structure_get_value (structure, "codec_data");
2008   if (value)
2009     buf = gst_value_get_buffer (value);
2010   if (buf != NULL) {
2011     guint8 *priv_data = NULL, *priv_buffer_data;
2012     gsize priv_data_size = 0;
2013
2014     priv_buffer_data =
2015         gst_buffer_map (buf, &priv_data_size, NULL, GST_MAP_READ);
2016     if (priv_data_size > SUBTITLE_MAX_CODEC_PRIVATE) {
2017       GST_WARNING_OBJECT (mux, "pad %" GST_PTR_FORMAT " subtitle private data"
2018           " exceeded maximum (%d); discarding", pad,
2019           SUBTITLE_MAX_CODEC_PRIVATE);
2020       gst_buffer_unmap (buf, priv_data, priv_data_size);
2021       return TRUE;
2022     }
2023
2024     gst_matroska_mux_free_codec_priv (context);
2025
2026     priv_data = g_malloc0 (priv_data_size);
2027     memcpy (priv_data, priv_buffer_data, priv_data_size);
2028     context->codec_priv = priv_data;
2029     context->codec_priv_size = priv_data_size;
2030     gst_buffer_unmap (buf, priv_buffer_data, priv_data_size);
2031   }
2032
2033   GST_DEBUG_OBJECT (pad, "codec_id %s, codec data size %" G_GSIZE_FORMAT,
2034       GST_STR_NULL (context->codec_id), context->codec_priv_size);
2035
2036 exit:
2037   /* free default if modified */
2038   if (id)
2039     g_free (id);
2040
2041   return ret;
2042 }
2043
2044
2045 /**
2046  * gst_matroska_mux_request_new_pad:
2047  * @element: #GstMatroskaMux.
2048  * @templ: #GstPadTemplate.
2049  * @pad_name: New pad name.
2050  *
2051  * Request pad function for sink templates.
2052  *
2053  * Returns: New #GstPad.
2054  */
2055 static GstPad *
2056 gst_matroska_mux_request_new_pad (GstElement * element,
2057     GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
2058 {
2059   GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
2060   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
2061   GstMatroskaPad *collect_pad;
2062   GstMatroskamuxPad *newpad;
2063   gchar *name = NULL;
2064   const gchar *pad_name = NULL;
2065   GstMatroskaCapsFunc capsfunc = NULL;
2066   GstMatroskaTrackContext *context = NULL;
2067   gint pad_id;
2068   gboolean locked = TRUE;
2069   gchar *id = NULL;
2070
2071   if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
2072     /* don't mix named and unnamed pads, if the pad already exists we fail when
2073      * trying to add it */
2074     if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
2075       pad_name = req_name;
2076     } else {
2077       name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
2078       pad_name = name;
2079     }
2080     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
2081     context = (GstMatroskaTrackContext *)
2082         g_new0 (GstMatroskaTrackAudioContext, 1);
2083     context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
2084     context->name = g_strdup ("Audio");
2085   } else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
2086     /* don't mix named and unnamed pads, if the pad already exists we fail when
2087      * trying to add it */
2088     if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
2089       pad_name = req_name;
2090     } else {
2091       name = g_strdup_printf ("video_%u", mux->num_v_streams++);
2092       pad_name = name;
2093     }
2094     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
2095     context = (GstMatroskaTrackContext *)
2096         g_new0 (GstMatroskaTrackVideoContext, 1);
2097     context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
2098     context->name = g_strdup ("Video");
2099   } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%u")) {
2100     /* don't mix named and unnamed pads, if the pad already exists we fail when
2101      * trying to add it */
2102     if (req_name != NULL && sscanf (req_name, "subtitle_%u", &pad_id) == 1) {
2103       pad_name = req_name;
2104     } else {
2105       name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++);
2106       pad_name = name;
2107     }
2108     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
2109     context = (GstMatroskaTrackContext *)
2110         g_new0 (GstMatroskaTrackSubtitleContext, 1);
2111     context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
2112     context->name = g_strdup ("Subtitle");
2113     /* setcaps may only provide proper one a lot later */
2114     id = g_strdup ("S_SUB_UNKNOWN");
2115     locked = FALSE;
2116   } else {
2117     GST_WARNING_OBJECT (mux, "This is not our template!");
2118     return NULL;
2119   }
2120
2121   newpad = g_object_new (GST_TYPE_MATROSKAMUX_PAD,
2122       "name", pad_name, "direction", templ->direction, "template", templ, NULL);
2123   g_free (name);
2124
2125   gst_matroskamux_pad_init (newpad);
2126   collect_pad = (GstMatroskaPad *)
2127       gst_collect_pads2_add_pad_full (mux->collect, GST_PAD (newpad),
2128       sizeof (GstMatroskamuxPad),
2129       (GstCollectData2DestroyNotify) gst_matroska_pad_free, locked);
2130
2131   collect_pad->track = context;
2132   gst_matroska_pad_reset (collect_pad, FALSE);
2133   collect_pad->track->codec_id = id;
2134
2135   collect_pad->capsfunc = capsfunc;
2136   gst_pad_set_active (GST_PAD (newpad), TRUE);
2137   if (!gst_element_add_pad (element, GST_PAD (newpad)))
2138     goto pad_add_failed;
2139
2140   mux->num_streams++;
2141
2142   GST_DEBUG_OBJECT (newpad, "Added new request pad");
2143
2144   return GST_PAD (newpad);
2145
2146   /* ERROR cases */
2147 pad_add_failed:
2148   {
2149     GST_WARNING_OBJECT (mux, "Adding the new pad '%s' failed", pad_name);
2150     gst_object_unref (newpad);
2151     return NULL;
2152   }
2153 }
2154
2155 /**
2156  * gst_matroska_mux_release_pad:
2157  * @element: #GstMatroskaMux.
2158  * @pad: Pad to release.
2159  *
2160  * Release a previously requested pad.
2161 */
2162 static void
2163 gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
2164 {
2165   GstMatroskaMux *mux;
2166   GSList *walk;
2167
2168   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
2169
2170   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
2171     GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
2172     GstMatroskaPad *collect_pad = (GstMatroskaPad *) cdata;
2173
2174     if (cdata->pad == pad) {
2175       GstClockTime min_dur;     /* observed minimum duration */
2176
2177       if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2178           GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2179         min_dur = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2180         if (collect_pad->duration < min_dur)
2181           collect_pad->duration = min_dur;
2182       }
2183
2184       if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
2185           mux->duration < collect_pad->duration)
2186         mux->duration = collect_pad->duration;
2187
2188       break;
2189     }
2190   }
2191
2192   gst_collect_pads2_remove_pad (mux->collect, pad);
2193   if (gst_element_remove_pad (element, pad))
2194     mux->num_streams--;
2195 }
2196
2197
2198 /**
2199  * gst_matroska_mux_track_header:
2200  * @mux: #GstMatroskaMux
2201  * @context: Tack context.
2202  *
2203  * Write a track header.
2204  */
2205 static void
2206 gst_matroska_mux_track_header (GstMatroskaMux * mux,
2207     GstMatroskaTrackContext * context)
2208 {
2209   GstEbmlWrite *ebml = mux->ebml_write;
2210   guint64 master;
2211
2212   /* TODO: check if everything necessary is written and check default values */
2213
2214   /* track type goes before the type-specific stuff */
2215   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKNUMBER, context->num);
2216   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKTYPE, context->type);
2217
2218   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKUID,
2219       gst_matroska_mux_create_uid ());
2220   if (context->default_duration) {
2221     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKDEFAULTDURATION,
2222         context->default_duration);
2223   }
2224   if (context->language) {
2225     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKLANGUAGE,
2226         context->language);
2227   }
2228
2229   /* FIXME: until we have a nice way of getting the codecname
2230    * out of the caps, I'm not going to enable this. Too much
2231    * (useless, double, boring) work... */
2232   /* TODO: Use value from tags if any */
2233   /*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
2234      context->codec_name); */
2235   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
2236
2237   /* type-specific stuff */
2238   switch (context->type) {
2239     case GST_MATROSKA_TRACK_TYPE_VIDEO:{
2240       GstMatroskaTrackVideoContext *videocontext =
2241           (GstMatroskaTrackVideoContext *) context;
2242
2243       master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKVIDEO);
2244       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELWIDTH,
2245           videocontext->pixel_width);
2246       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELHEIGHT,
2247           videocontext->pixel_height);
2248       if (videocontext->display_width && videocontext->display_height) {
2249         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEODISPLAYWIDTH,
2250             videocontext->display_width);
2251         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEODISPLAYHEIGHT,
2252             videocontext->display_height);
2253       }
2254       if (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED)
2255         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOFLAGINTERLACED, 1);
2256       if (videocontext->fourcc) {
2257         guint32 fcc_le = GUINT32_TO_LE (videocontext->fourcc);
2258
2259         gst_ebml_write_binary (ebml, GST_MATROSKA_ID_VIDEOCOLOURSPACE,
2260             (gpointer) & fcc_le, 4);
2261       }
2262       gst_ebml_write_master_finish (ebml, master);
2263
2264       break;
2265     }
2266
2267     case GST_MATROSKA_TRACK_TYPE_AUDIO:{
2268       GstMatroskaTrackAudioContext *audiocontext =
2269           (GstMatroskaTrackAudioContext *) context;
2270
2271       master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKAUDIO);
2272       if (audiocontext->samplerate != 8000)
2273         gst_ebml_write_float (ebml, GST_MATROSKA_ID_AUDIOSAMPLINGFREQ,
2274             audiocontext->samplerate);
2275       if (audiocontext->channels != 1)
2276         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOCHANNELS,
2277             audiocontext->channels);
2278       if (audiocontext->bitdepth) {
2279         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOBITDEPTH,
2280             audiocontext->bitdepth);
2281       }
2282       gst_ebml_write_master_finish (ebml, master);
2283
2284       break;
2285     }
2286
2287       /* this is what we write for now and must be filled
2288        * and remainder void'ed later on */
2289 #define SUBTITLE_DUMMY_SIZE   (1 + 1 + 14 + 1 + 2 + SUBTITLE_MAX_CODEC_PRIVATE)
2290
2291     case GST_MATROSKA_TRACK_TYPE_SUBTITLE:{
2292       gpointer buf;
2293
2294       context->pos = ebml->pos;
2295       /* CodecID is mandatory ... */
2296       gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CODECID, "S_SUB_UNKNOWN");
2297       /* reserve space */
2298       buf = g_malloc0 (SUBTITLE_MAX_CODEC_PRIVATE);
2299       gst_ebml_write_binary (ebml, GST_EBML_ID_VOID, buf,
2300           SUBTITLE_MAX_CODEC_PRIVATE);
2301       g_free (buf);
2302       /* real data has to be written at finish */
2303       return;
2304     }
2305     default:
2306       /* doesn't need type-specific data */
2307       break;
2308   }
2309
2310   gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CODECID, context->codec_id);
2311   if (context->codec_priv)
2312     gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
2313         context->codec_priv, context->codec_priv_size);
2314 }
2315
2316
2317 /**
2318  * gst_matroska_mux_start:
2319  * @mux: #GstMatroskaMux
2320  *
2321  * Start a new matroska file (write headers etc...)
2322  */
2323 static void
2324 gst_matroska_mux_start (GstMatroskaMux * mux)
2325 {
2326   GstEbmlWrite *ebml = mux->ebml_write;
2327   const gchar *doctype;
2328   guint32 seekhead_id[] = { GST_MATROSKA_ID_SEGMENTINFO,
2329     GST_MATROSKA_ID_TRACKS,
2330     GST_MATROSKA_ID_CUES,
2331     GST_MATROSKA_ID_TAGS,
2332     0
2333   };
2334   guint64 master, child;
2335   GSList *collected;
2336   int i;
2337   guint tracknum = 1;
2338   GstClockTime duration = 0;
2339   guint32 segment_uid[4];
2340   GTimeVal time = { 0, 0 };
2341
2342   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
2343     ebml->caps = gst_caps_new_empty_simple ("video/webm");
2344   } else {
2345     ebml->caps = gst_caps_new_empty_simple ("video/x-matroska");
2346   }
2347   /* we start with a EBML header */
2348   doctype = mux->doctype;
2349   GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
2350       doctype, mux->doctype_version);
2351   gst_ebml_write_header (ebml, doctype, mux->doctype_version);
2352
2353   /* the rest of the header is cached */
2354   gst_ebml_write_set_cache (ebml, 0x1000);
2355
2356   /* start a segment */
2357   mux->segment_pos =
2358       gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENT);
2359   mux->segment_master = ebml->pos;
2360
2361   if (!mux->streamable) {
2362     /* seekhead (table of contents) - we set the positions later */
2363     mux->seekhead_pos = ebml->pos;
2364     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKHEAD);
2365     for (i = 0; seekhead_id[i] != 0; i++) {
2366       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKENTRY);
2367       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKID, seekhead_id[i]);
2368       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKPOSITION, -1);
2369       gst_ebml_write_master_finish (ebml, child);
2370     }
2371     gst_ebml_write_master_finish (ebml, master);
2372   }
2373
2374   if (mux->streamable) {
2375     const GstTagList *tags;
2376
2377     /* tags */
2378     tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2379
2380     if (tags != NULL && !gst_tag_list_is_empty (tags)) {
2381       guint64 master_tags, master_tag;
2382
2383       GST_DEBUG_OBJECT (mux, "Writing tags");
2384
2385       /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2386       mux->tags_pos = ebml->pos;
2387       master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2388       master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2389       gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2390       gst_ebml_write_master_finish (ebml, master_tag);
2391       gst_ebml_write_master_finish (ebml, master_tags);
2392     }
2393   }
2394
2395   /* segment info */
2396   mux->info_pos = ebml->pos;
2397   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);
2398   for (i = 0; i < 4; i++) {
2399     segment_uid[i] = g_random_int ();
2400   }
2401   gst_ebml_write_binary (ebml, GST_MATROSKA_ID_SEGMENTUID,
2402       (guint8 *) segment_uid, 16);
2403   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TIMECODESCALE, mux->time_scale);
2404   mux->duration_pos = ebml->pos;
2405   /* get duration */
2406   if (!mux->streamable) {
2407     for (collected = mux->collect->data; collected;
2408         collected = g_slist_next (collected)) {
2409       GstMatroskaPad *collect_pad;
2410       GstPad *thepad;
2411       gint64 trackduration;
2412
2413       collect_pad = (GstMatroskaPad *) collected->data;
2414       thepad = collect_pad->collect.pad;
2415
2416       /* Query the total length of the track. */
2417       GST_DEBUG_OBJECT (thepad, "querying peer duration");
2418       if (gst_pad_peer_query_duration (thepad, GST_FORMAT_TIME, &trackduration)) {
2419         GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
2420             GST_TIME_ARGS (trackduration));
2421         if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
2422           duration = (GstClockTime) trackduration;
2423         }
2424       }
2425     }
2426     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2427         gst_guint64_to_gdouble (duration) /
2428         gst_guint64_to_gdouble (mux->time_scale));
2429   }
2430   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_MUXINGAPP,
2431       "GStreamer plugin version " PACKAGE_VERSION);
2432   if (mux->writing_app && mux->writing_app[0]) {
2433     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, mux->writing_app);
2434   }
2435   g_get_current_time (&time);
2436   gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time.tv_sec);
2437   gst_ebml_write_master_finish (ebml, master);
2438
2439   /* tracks */
2440   mux->tracks_pos = ebml->pos;
2441   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKS);
2442
2443   for (collected = mux->collect->data; collected;
2444       collected = g_slist_next (collected)) {
2445     GstMatroskaPad *collect_pad;
2446     GstPad *thepad;
2447
2448     collect_pad = (GstMatroskaPad *) collected->data;
2449     thepad = collect_pad->collect.pad;
2450
2451     if (gst_pad_is_linked (thepad) && gst_pad_is_active (thepad) &&
2452         collect_pad->track->codec_id != 0) {
2453       collect_pad->track->num = tracknum++;
2454       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
2455       gst_matroska_mux_track_header (mux, collect_pad->track);
2456       gst_ebml_write_master_finish (ebml, child);
2457       /* some remaining pad/track setup */
2458       collect_pad->default_duration_scaled =
2459           gst_util_uint64_scale (collect_pad->track->default_duration,
2460           1, mux->time_scale);
2461     }
2462   }
2463   gst_ebml_write_master_finish (ebml, master);
2464
2465   /* lastly, flush the cache */
2466   gst_ebml_write_flush_cache (ebml, FALSE, 0);
2467 }
2468
2469 static void
2470 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
2471     gpointer data)
2472 {
2473   /* TODO: more sensible tag mappings */
2474   static const struct
2475   {
2476     const gchar *matroska_tagname;
2477     const gchar *gstreamer_tagname;
2478   }
2479   tag_conv[] = {
2480     {
2481     GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2482     GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
2483     GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2484     GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2485     GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2486     GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2487     GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2488     GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2489     GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2490     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2491     GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2492     GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2493     GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2494     GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2495     GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2496   };
2497   GstEbmlWrite *ebml = (GstEbmlWrite *) data;
2498   guint i;
2499   guint64 simpletag_master;
2500
2501   for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
2502     const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2503     const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2504
2505     if (strcmp (tagname_gst, tag) == 0) {
2506       GValue src = { 0, };
2507       gchar *dest;
2508
2509       if (!gst_tag_list_copy_value (&src, list, tag))
2510         break;
2511       if ((dest = gst_value_serialize (&src))) {
2512
2513         simpletag_master = gst_ebml_write_master_start (ebml,
2514             GST_MATROSKA_ID_SIMPLETAG);
2515         gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_TAGNAME, tagname_mkv);
2516         gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TAGSTRING, dest);
2517         gst_ebml_write_master_finish (ebml, simpletag_master);
2518         g_free (dest);
2519       } else {
2520         GST_WARNING ("Can't transform tag '%s' to string", tagname_mkv);
2521       }
2522       g_value_unset (&src);
2523       break;
2524     }
2525   }
2526 }
2527
2528
2529 /**
2530  * gst_matroska_mux_finish:
2531  * @mux: #GstMatroskaMux
2532  *
2533  * Finish a new matroska file (write index etc...)
2534  */
2535 static void
2536 gst_matroska_mux_finish (GstMatroskaMux * mux)
2537 {
2538   GstEbmlWrite *ebml = mux->ebml_write;
2539   guint64 pos;
2540   guint64 duration = 0;
2541   GSList *collected;
2542   const GstTagList *tags;
2543
2544   /* finish last cluster */
2545   if (mux->cluster) {
2546     gst_ebml_write_master_finish (ebml, mux->cluster);
2547   }
2548
2549   /* cues */
2550   if (mux->index != NULL) {
2551     guint n;
2552     guint64 master, pointentry_master, trackpos_master;
2553
2554     mux->cues_pos = ebml->pos;
2555     gst_ebml_write_set_cache (ebml, 12 + 41 * mux->num_indexes);
2556     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CUES);
2557
2558     for (n = 0; n < mux->num_indexes; n++) {
2559       GstMatroskaIndex *idx = &mux->index[n];
2560
2561       pointentry_master = gst_ebml_write_master_start (ebml,
2562           GST_MATROSKA_ID_POINTENTRY);
2563       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETIME,
2564           idx->time / mux->time_scale);
2565       trackpos_master = gst_ebml_write_master_start (ebml,
2566           GST_MATROSKA_ID_CUETRACKPOSITIONS);
2567       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETRACK, idx->track);
2568       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUECLUSTERPOSITION,
2569           idx->pos - mux->segment_master);
2570       gst_ebml_write_master_finish (ebml, trackpos_master);
2571       gst_ebml_write_master_finish (ebml, pointentry_master);
2572     }
2573
2574     gst_ebml_write_master_finish (ebml, master);
2575     gst_ebml_write_flush_cache (ebml, FALSE, GST_CLOCK_TIME_NONE);
2576   }
2577
2578   /* tags */
2579   tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2580
2581   if (tags != NULL && !gst_tag_list_is_empty (tags)) {
2582     guint64 master_tags, master_tag;
2583
2584     GST_DEBUG_OBJECT (mux, "Writing tags");
2585
2586     /* TODO: maybe limit via the TARGETS id by looking at the source pad */
2587     mux->tags_pos = ebml->pos;
2588     master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2589     master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2590     gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2591     gst_ebml_write_master_finish (ebml, master_tag);
2592     gst_ebml_write_master_finish (ebml, master_tags);
2593   }
2594
2595   /* update seekhead. We know that:
2596    * - a seekhead contains 4 entries.
2597    * - order of entries is as above.
2598    * - a seekhead has a 4-byte header + 8-byte length
2599    * - each entry is 2-byte master, 2-byte ID pointer,
2600    *     2-byte length pointer, all 8/1-byte length, 4-
2601    *     byte ID and 8-byte length pointer, where the
2602    *     length pointer starts at 20.
2603    * - all entries are local to the segment (so pos - segment_master).
2604    * - so each entry is at 12 + 20 + num * 28. */
2605   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
2606       mux->info_pos - mux->segment_master);
2607   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
2608       mux->tracks_pos - mux->segment_master);
2609   if (mux->index != NULL) {
2610     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 88,
2611         mux->cues_pos - mux->segment_master);
2612   } else {
2613     /* void'ify */
2614     guint64 my_pos = ebml->pos;
2615
2616     gst_ebml_write_seek (ebml, mux->seekhead_pos + 68);
2617     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2618     gst_ebml_write_seek (ebml, my_pos);
2619   }
2620   if (tags != NULL) {
2621     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 116,
2622         mux->tags_pos - mux->segment_master);
2623   } else {
2624     /* void'ify */
2625     guint64 my_pos = ebml->pos;
2626
2627     gst_ebml_write_seek (ebml, mux->seekhead_pos + 96);
2628     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
2629     gst_ebml_write_seek (ebml, my_pos);
2630   }
2631
2632   /* loop tracks:
2633    * - first get the overall duration
2634    *   (a released track may have left a duration in here)
2635    * - write some track header data for subtitles
2636    */
2637   duration = mux->duration;
2638   pos = ebml->pos;
2639   for (collected = mux->collect->data; collected;
2640       collected = g_slist_next (collected)) {
2641     GstMatroskaPad *collect_pad;
2642     GstClockTime min_duration;  /* observed minimum duration */
2643     GstMatroskaTrackContext *context;
2644     gint voidleft = 0, fill = 0;
2645     gpointer codec_id;
2646
2647     collect_pad = (GstMatroskaPad *) collected->data;
2648     context = collect_pad->track;
2649
2650     GST_DEBUG_OBJECT (mux,
2651         "Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
2652         " end ts %" GST_TIME_FORMAT, collect_pad,
2653         GST_TIME_ARGS (collect_pad->start_ts),
2654         GST_TIME_ARGS (collect_pad->end_ts));
2655
2656     if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2657         GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2658       min_duration =
2659           GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2660       if (collect_pad->duration < min_duration)
2661         collect_pad->duration = min_duration;
2662       GST_DEBUG_OBJECT (collect_pad,
2663           "final track duration: %" GST_TIME_FORMAT,
2664           GST_TIME_ARGS (collect_pad->duration));
2665     }
2666
2667     if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
2668         duration < collect_pad->duration)
2669       duration = collect_pad->duration;
2670
2671     if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE || !context->pos)
2672       continue;
2673
2674   again:
2675     /* write subtitle type and possible private data */
2676     gst_ebml_write_seek (ebml, context->pos);
2677     /* complex way to write ascii to account for extra filling */
2678     codec_id = g_malloc0 (strlen (context->codec_id) + 1 + fill);
2679     strcpy (codec_id, context->codec_id);
2680     gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECID,
2681         codec_id, strlen (context->codec_id) + 1 + fill);
2682     g_free (codec_id);
2683     if (context->codec_priv)
2684       gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
2685           context->codec_priv, context->codec_priv_size);
2686     voidleft = SUBTITLE_DUMMY_SIZE - (ebml->pos - context->pos);
2687     /* void'ify; sigh, variable sized length field */
2688     if (voidleft == 1) {
2689       fill = 1;
2690       goto again;
2691     } else if (voidleft && voidleft <= 128)
2692       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 2);
2693     else if (voidleft >= 130)
2694       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 3);
2695     else if (voidleft == 129) {
2696       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 64);
2697       gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 63);
2698     }
2699   }
2700
2701   /* seek back (optional, but do anyway) */
2702   gst_ebml_write_seek (ebml, pos);
2703
2704   /* update duration */
2705   if (duration != 0) {
2706     GST_DEBUG_OBJECT (mux, "final total duration: %" GST_TIME_FORMAT,
2707         GST_TIME_ARGS (duration));
2708     pos = mux->ebml_write->pos;
2709     gst_ebml_write_seek (ebml, mux->duration_pos);
2710     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2711         gst_guint64_to_gdouble (duration) /
2712         gst_guint64_to_gdouble (mux->time_scale));
2713     gst_ebml_write_seek (ebml, pos);
2714   } else {
2715     /* void'ify */
2716     guint64 my_pos = ebml->pos;
2717
2718     gst_ebml_write_seek (ebml, mux->duration_pos);
2719     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 8);
2720     gst_ebml_write_seek (ebml, my_pos);
2721   }
2722   GST_DEBUG_OBJECT (mux, "finishing segment");
2723   /* finish segment - this also writes element length */
2724   gst_ebml_write_master_finish (ebml, mux->segment_pos);
2725 }
2726
2727 /**
2728  * gst_matroska_mux_buffer_header:
2729  * @track: Track context.
2730  * @relative_timestamp: relative timestamp of the buffer
2731  * @flags: Buffer flags.
2732  *
2733  * Create a buffer containing buffer header.
2734  *
2735  * Returns: New buffer.
2736  */
2737 static GstBuffer *
2738 gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
2739     gint16 relative_timestamp, int flags)
2740 {
2741   GstBuffer *hdr;
2742   guint8 *data = g_malloc (4);
2743
2744   hdr = gst_buffer_new_wrapped (data, 4);
2745   /* track num - FIXME: what if num >= 0x80 (unlikely)? */
2746   data[0] = track->num | 0x80;
2747   /* time relative to clustertime */
2748   GST_WRITE_UINT16_BE (data + 1, relative_timestamp);
2749
2750   /* flags */
2751   data[3] = flags;
2752
2753   return hdr;
2754 }
2755
2756 #define DIRAC_PARSE_CODE_SEQUENCE_HEADER 0x00
2757 #define DIRAC_PARSE_CODE_END_OF_SEQUENCE 0x10
2758 #define DIRAC_PARSE_CODE_IS_PICTURE(x) ((x & 0x08) != 0)
2759
2760 static GstBuffer *
2761 gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
2762     GstMatroskaPad * collect_pad, GstBuffer * buf)
2763 {
2764   GstMatroskaTrackVideoContext *ctx =
2765       (GstMatroskaTrackVideoContext *) collect_pad->track;
2766   guint8 *buf_data, *data;
2767   gsize size;
2768   guint8 parse_code;
2769   guint32 next_parse_offset;
2770   GstBuffer *ret = NULL;
2771   gboolean is_muxing_unit = FALSE;
2772
2773   buf_data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
2774   data = buf_data;
2775
2776   if (size < 13) {
2777     gst_buffer_unmap (buf, buf_data, -1);
2778     gst_buffer_unref (buf);
2779     return ret;
2780   }
2781
2782   /* Check if this buffer contains a picture or end-of-sequence packet */
2783   while (size >= 13) {
2784     if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) {
2785       gst_buffer_unmap (buf, buf_data, -1);
2786       gst_buffer_unref (buf);
2787       return ret;
2788     }
2789
2790     parse_code = GST_READ_UINT8 (data + 4);
2791     if (parse_code == DIRAC_PARSE_CODE_SEQUENCE_HEADER) {
2792       if (ctx->dirac_unit) {
2793         gst_buffer_unref (ctx->dirac_unit);
2794         ctx->dirac_unit = NULL;
2795       }
2796     } else if (DIRAC_PARSE_CODE_IS_PICTURE (parse_code) ||
2797         parse_code == DIRAC_PARSE_CODE_END_OF_SEQUENCE) {
2798       is_muxing_unit = TRUE;
2799       break;
2800     }
2801
2802     next_parse_offset = GST_READ_UINT32_BE (data + 5);
2803
2804     if (G_UNLIKELY (next_parse_offset == 0 || next_parse_offset > size))
2805       break;
2806
2807     data += next_parse_offset;
2808     size -= next_parse_offset;
2809   }
2810
2811   if (ctx->dirac_unit)
2812     ctx->dirac_unit = gst_buffer_join (ctx->dirac_unit, gst_buffer_ref (buf));
2813   else
2814     ctx->dirac_unit = gst_buffer_ref (buf);
2815
2816   gst_buffer_unmap (buf, buf_data, -1);
2817
2818   if (is_muxing_unit) {
2819     ret = gst_buffer_make_writable (ctx->dirac_unit);
2820     ctx->dirac_unit = NULL;
2821     gst_buffer_copy_into (ret, buf,
2822         GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2823     gst_buffer_unref (buf);
2824   } else {
2825     gst_buffer_unref (buf);
2826     ret = NULL;
2827   }
2828
2829   return ret;
2830 }
2831
2832 static void
2833 gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
2834 {
2835   GstCaps *caps;
2836   GstStructure *s;
2837   GValue streamheader = { 0 };
2838   GValue bufval = { 0 };
2839   GstBuffer *streamheader_buffer;
2840   GstEbmlWrite *ebml = mux->ebml_write;
2841
2842   streamheader_buffer = gst_ebml_stop_streamheader (ebml);
2843   if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
2844     caps = gst_caps_new_empty_simple ("video/webm");
2845   } else {
2846     caps = gst_caps_new_empty_simple ("video/x-matroska");
2847   }
2848   s = gst_caps_get_structure (caps, 0);
2849   g_value_init (&streamheader, GST_TYPE_ARRAY);
2850   g_value_init (&bufval, GST_TYPE_BUFFER);
2851   GST_BUFFER_FLAG_SET (streamheader_buffer, GST_BUFFER_FLAG_IN_CAPS);
2852   gst_value_set_buffer (&bufval, streamheader_buffer);
2853   gst_value_array_append_value (&streamheader, &bufval);
2854   g_value_unset (&bufval);
2855   gst_structure_set_value (s, "streamheader", &streamheader);
2856   g_value_unset (&streamheader);
2857   gst_caps_replace (&ebml->caps, caps);
2858   gst_buffer_unref (streamheader_buffer);
2859   gst_caps_unref (caps);
2860 }
2861
2862 /**
2863  * gst_matroska_mux_write_data:
2864  * @mux: #GstMatroskaMux
2865  * @collect_pad: #GstMatroskaPad with the data
2866  *
2867  * Write collected data (called from gst_matroska_mux_collected).
2868  *
2869  * Returns: Result of the gst_pad_push issued to write the data.
2870  */
2871 static GstFlowReturn
2872 gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
2873     GstBuffer * buf)
2874 {
2875   GstEbmlWrite *ebml = mux->ebml_write;
2876   GstBuffer *hdr;
2877   guint64 blockgroup;
2878   gboolean write_duration;
2879   gint16 relative_timestamp;
2880   gint64 relative_timestamp64;
2881   guint64 block_duration;
2882   gboolean is_video_keyframe = FALSE;
2883   GstMatroskamuxPad *pad;
2884
2885   /* write data */
2886   pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
2887
2888   /* vorbis/theora headers are retrieved from caps and put in CodecPrivate */
2889   if (collect_pad->track->xiph_headers_to_skip > 0) {
2890     GST_LOG_OBJECT (collect_pad->collect.pad, "dropping streamheader buffer");
2891     gst_buffer_unref (buf);
2892     --collect_pad->track->xiph_headers_to_skip;
2893     return GST_FLOW_OK;
2894   }
2895
2896   /* for dirac we have to queue up everything up to a picture unit */
2897   if (collect_pad->track->codec_id != NULL &&
2898       strcmp (collect_pad->track->codec_id,
2899           GST_MATROSKA_CODEC_ID_VIDEO_DIRAC) == 0) {
2900     buf = gst_matroska_mux_handle_dirac_packet (mux, collect_pad, buf);
2901     if (!buf)
2902       return GST_FLOW_OK;
2903   }
2904
2905   /* hm, invalid timestamp (due to --to be fixed--- element upstream);
2906    * this would wreak havoc with time stored in matroska file */
2907   /* TODO: maybe calculate a timestamp by using the previous timestamp
2908    * and default duration */
2909   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2910     GST_WARNING_OBJECT (collect_pad->collect.pad,
2911         "Invalid buffer timestamp; dropping buffer");
2912     gst_buffer_unref (buf);
2913     return GST_FLOW_OK;
2914   }
2915
2916   /* set the timestamp for outgoing buffers */
2917   ebml->timestamp = GST_BUFFER_TIMESTAMP (buf);
2918
2919   if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
2920       !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
2921     GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT,
2922         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
2923     is_video_keyframe = TRUE;
2924   }
2925
2926   if (mux->cluster) {
2927     /* start a new cluster at every keyframe, at every GstForceKeyUnit event,
2928      * or when we may be reaching the limit of the relative timestamp */
2929     if (mux->cluster_time +
2930         mux->max_cluster_duration < GST_BUFFER_TIMESTAMP (buf)
2931         || is_video_keyframe || mux->force_key_unit_event) {
2932       if (!mux->streamable)
2933         gst_ebml_write_master_finish (ebml, mux->cluster);
2934
2935       /* Forward the GstForceKeyUnit event after finishing the cluster */
2936       if (mux->force_key_unit_event) {
2937         gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
2938         mux->force_key_unit_event = NULL;
2939       }
2940
2941       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
2942       mux->cluster_pos = ebml->pos;
2943       gst_ebml_write_set_cache (ebml, 0x20);
2944       mux->cluster =
2945           gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2946       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2947           gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
2948               mux->time_scale));
2949       GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
2950           gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
2951               mux->time_scale));
2952       gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
2953       mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2954       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
2955           mux->prev_cluster_size);
2956     }
2957   } else {
2958     /* first cluster */
2959
2960     mux->cluster_pos = ebml->pos;
2961     gst_ebml_write_set_cache (ebml, 0x20);
2962     mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
2963     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
2964         gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1, mux->time_scale));
2965     gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
2966     mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
2967   }
2968
2969   /* update duration of this track */
2970   if (GST_BUFFER_DURATION_IS_VALID (buf))
2971     collect_pad->duration += GST_BUFFER_DURATION (buf);
2972
2973   /* We currently write index entries for all video tracks or for the audio
2974    * track in a single-track audio file.  This could be improved by keeping the
2975    * index only for the *first* video track. */
2976
2977   /* TODO: index is useful for every track, should contain the number of
2978    * the block in the cluster which contains the timestamp, should also work
2979    * for files with multiple audio tracks.
2980    */
2981   if (!mux->streamable &&
2982       (is_video_keyframe ||
2983           ((collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO) &&
2984               (mux->num_streams == 1)))) {
2985     gint last_idx = -1;
2986
2987     if (mux->min_index_interval != 0) {
2988       for (last_idx = mux->num_indexes - 1; last_idx >= 0; last_idx--) {
2989         if (mux->index[last_idx].track == collect_pad->track->num)
2990           break;
2991       }
2992     }
2993
2994     if (last_idx < 0 || mux->min_index_interval == 0 ||
2995         (GST_CLOCK_DIFF (mux->index[last_idx].time, GST_BUFFER_TIMESTAMP (buf))
2996             >= mux->min_index_interval)) {
2997       GstMatroskaIndex *idx;
2998
2999       if (mux->num_indexes % 32 == 0) {
3000         mux->index = g_renew (GstMatroskaIndex, mux->index,
3001             mux->num_indexes + 32);
3002       }
3003       idx = &mux->index[mux->num_indexes++];
3004
3005       idx->pos = mux->cluster_pos;
3006       idx->time = GST_BUFFER_TIMESTAMP (buf);
3007       idx->track = collect_pad->track->num;
3008     }
3009   }
3010
3011   /* Check if the duration differs from the default duration. */
3012   write_duration = FALSE;
3013   block_duration = 0;
3014   if (pad->frame_duration && GST_BUFFER_DURATION_IS_VALID (buf)) {
3015     block_duration = gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
3016         1, mux->time_scale);
3017
3018     /* small difference should be ok. */
3019     if (block_duration > collect_pad->default_duration_scaled + 1 ||
3020         block_duration < collect_pad->default_duration_scaled - 1) {
3021       write_duration = TRUE;
3022     }
3023   }
3024
3025   /* write the block, for doctype v2 use SimpleBlock if possible
3026    * one slice (*breath*).
3027    * FIXME: Need to do correct lacing! */
3028   relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time;
3029   if (relative_timestamp64 >= 0) {
3030     /* round the timestamp */
3031     relative_timestamp64 += gst_util_uint64_scale (mux->time_scale, 1, 2);
3032   } else {
3033     /* round the timestamp */
3034     relative_timestamp64 -= gst_util_uint64_scale (mux->time_scale, 1, 2);
3035   }
3036   relative_timestamp = gst_util_uint64_scale (relative_timestamp64, 1,
3037       mux->time_scale);
3038   if (mux->doctype_version > 1 && !write_duration) {
3039     int flags =
3040         GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : 0x80;
3041
3042     hdr =
3043         gst_matroska_mux_create_buffer_header (collect_pad->track,
3044         relative_timestamp, flags);
3045     gst_ebml_write_set_cache (ebml, 0x40);
3046     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
3047         gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
3048     gst_ebml_write_buffer (ebml, hdr);
3049     gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
3050     gst_ebml_write_buffer (ebml, buf);
3051
3052     return gst_ebml_last_write_result (ebml);
3053   } else {
3054     gst_ebml_write_set_cache (ebml, gst_buffer_get_size (buf) * 2);
3055     /* write and call order slightly unnatural,
3056      * but avoids seek and minizes pushing */
3057     blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
3058     hdr =
3059         gst_matroska_mux_create_buffer_header (collect_pad->track,
3060         relative_timestamp, 0);
3061     if (write_duration)
3062       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
3063     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
3064         gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
3065     gst_ebml_write_buffer (ebml, hdr);
3066     gst_ebml_write_master_finish_full (ebml, blockgroup,
3067         gst_buffer_get_size (buf));
3068     gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
3069     gst_ebml_write_buffer (ebml, buf);
3070
3071     return gst_ebml_last_write_result (ebml);
3072   }
3073 }
3074
3075 /**
3076  * gst_matroska_mux_handle_buffer:
3077  * @pads: #GstCollectPads2
3078  * @uuser_data: #GstMatroskaMux
3079  *
3080  * Collectpads callback.
3081  *
3082  * Returns: #GstFlowReturn
3083  */
3084 static GstFlowReturn
3085 gst_matroska_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
3086     GstBuffer * buf, gpointer user_data)
3087 {
3088   GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
3089   GstEbmlWrite *ebml = mux->ebml_write;
3090   GstMatroskaPad *best;
3091   GstFlowReturn ret = GST_FLOW_OK;
3092
3093   GST_DEBUG_OBJECT (mux, "Collected pads");
3094
3095   /* start with a header */
3096   if (mux->state == GST_MATROSKA_MUX_STATE_START) {
3097     if (mux->collect->data == NULL) {
3098       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
3099           ("No input streams configured"));
3100       return GST_FLOW_ERROR;
3101     }
3102     mux->state = GST_MATROSKA_MUX_STATE_HEADER;
3103     gst_ebml_start_streamheader (ebml);
3104     gst_matroska_mux_start (mux);
3105     gst_matroska_mux_stop_streamheader (mux);
3106     mux->state = GST_MATROSKA_MUX_STATE_DATA;
3107   }
3108
3109   /* provided with stream to write from */
3110   best = (GstMatroskaPad *) data;
3111
3112   /* if there is no best pad, we have reached EOS */
3113   if (best == NULL) {
3114     GST_DEBUG_OBJECT (mux, "No best pad finishing...");
3115     if (!mux->streamable) {
3116       gst_matroska_mux_finish (mux);
3117     } else {
3118       GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
3119     }
3120     gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
3121     ret = GST_FLOW_EOS;
3122     goto exit;
3123   }
3124
3125   /* if we have a best stream, should also have a buffer */
3126   g_assert (buf);
3127
3128   GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
3129       GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
3130       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
3131       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
3132
3133   /* make note of first and last encountered timestamps, so we can calculate
3134    * the actual duration later when we send an updated header on eos */
3135   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
3136     GstClockTime start_ts = GST_BUFFER_TIMESTAMP (buf);
3137     GstClockTime end_ts = start_ts;
3138
3139     if (GST_BUFFER_DURATION_IS_VALID (buf))
3140       end_ts += GST_BUFFER_DURATION (buf);
3141     else if (best->track->default_duration)
3142       end_ts += best->track->default_duration;
3143
3144     if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
3145       best->end_ts = end_ts;
3146
3147     if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
3148             start_ts < best->start_ts))
3149       best->start_ts = start_ts;
3150   }
3151
3152   /* write one buffer */
3153   ret = gst_matroska_mux_write_data (mux, best, buf);
3154
3155 exit:
3156   return ret;
3157 }
3158
3159
3160 /**
3161  * gst_matroska_mux_change_state:
3162  * @element: #GstMatroskaMux
3163  * @transition: State change transition.
3164  *
3165  * Change the muxer state.
3166  *
3167  * Returns: #GstStateChangeReturn
3168  */
3169 static GstStateChangeReturn
3170 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
3171 {
3172   GstStateChangeReturn ret;
3173   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
3174
3175   switch (transition) {
3176     case GST_STATE_CHANGE_NULL_TO_READY:
3177       break;
3178     case GST_STATE_CHANGE_READY_TO_PAUSED:
3179       gst_collect_pads2_start (mux->collect);
3180       break;
3181     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3182       break;
3183     case GST_STATE_CHANGE_PAUSED_TO_READY:
3184       gst_collect_pads2_stop (mux->collect);
3185       break;
3186     default:
3187       break;
3188   }
3189
3190   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3191
3192   switch (transition) {
3193     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3194       break;
3195     case GST_STATE_CHANGE_PAUSED_TO_READY:
3196       gst_matroska_mux_reset (GST_ELEMENT (mux));
3197       break;
3198     case GST_STATE_CHANGE_READY_TO_NULL:
3199       break;
3200     default:
3201       break;
3202   }
3203
3204   return ret;
3205 }
3206
3207 static void
3208 gst_matroska_mux_set_property (GObject * object,
3209     guint prop_id, const GValue * value, GParamSpec * pspec)
3210 {
3211   GstMatroskaMux *mux;
3212
3213   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3214   mux = GST_MATROSKA_MUX (object);
3215
3216   switch (prop_id) {
3217     case ARG_WRITING_APP:
3218       if (!g_value_get_string (value)) {
3219         GST_WARNING_OBJECT (mux, "writing-app property can not be NULL");
3220         break;
3221       }
3222       g_free (mux->writing_app);
3223       mux->writing_app = g_value_dup_string (value);
3224       break;
3225     case ARG_DOCTYPE_VERSION:
3226       mux->doctype_version = g_value_get_int (value);
3227       break;
3228     case ARG_MIN_INDEX_INTERVAL:
3229       mux->min_index_interval = g_value_get_int64 (value);
3230       break;
3231     case ARG_STREAMABLE:
3232       mux->streamable = g_value_get_boolean (value);
3233       break;
3234     default:
3235       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3236       break;
3237   }
3238 }
3239
3240 static void
3241 gst_matroska_mux_get_property (GObject * object,
3242     guint prop_id, GValue * value, GParamSpec * pspec)
3243 {
3244   GstMatroskaMux *mux;
3245
3246   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3247   mux = GST_MATROSKA_MUX (object);
3248
3249   switch (prop_id) {
3250     case ARG_WRITING_APP:
3251       g_value_set_string (value, mux->writing_app);
3252       break;
3253     case ARG_DOCTYPE_VERSION:
3254       g_value_set_int (value, mux->doctype_version);
3255       break;
3256     case ARG_MIN_INDEX_INTERVAL:
3257       g_value_set_int64 (value, mux->min_index_interval);
3258       break;
3259     case ARG_STREAMABLE:
3260       g_value_set_boolean (value, mux->streamable);
3261       break;
3262     default:
3263       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3264       break;
3265   }
3266 }