matroska: use math-compat.h for NAN define
[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., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, 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-1.0 -v filesrc location=/path/to/mp3 ! mpegaudioparse ! 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-1.0 -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 #include <gst/pbutils/codec-utils.h>
57
58 #include "matroska-mux.h"
59 #include "matroska-ids.h"
60
61 #define GST_MATROSKA_MUX_CHAPLANG "und"
62
63 GST_DEBUG_CATEGORY_STATIC (matroskamux_debug);
64 #define GST_CAT_DEFAULT matroskamux_debug
65
66 enum
67 {
68   PROP_0,
69   PROP_WRITING_APP,
70   PROP_DOCTYPE_VERSION,
71   PROP_MIN_INDEX_INTERVAL,
72   PROP_STREAMABLE,
73   PROP_TIMECODESCALE
74 };
75
76 #define  DEFAULT_DOCTYPE_VERSION         2
77 #define  DEFAULT_WRITING_APP             "GStreamer Matroska muxer"
78 #define  DEFAULT_MIN_INDEX_INTERVAL      0
79 #define  DEFAULT_STREAMABLE              FALSE
80 #define  DEFAULT_TIMECODESCALE           GST_MSECOND
81
82 /* WAVEFORMATEX is gst_riff_strf_auds + an extra guint16 extension size */
83 #define WAVEFORMATEX_SIZE  (2 + sizeof (gst_riff_strf_auds))
84
85 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
86     GST_PAD_SRC,
87     GST_PAD_ALWAYS,
88     GST_STATIC_CAPS ("video/x-matroska; video/x-matroska-3d; audio/x-matroska")
89     );
90
91 #define COMMON_VIDEO_CAPS \
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-h265, stream-format=hvc1, alignment=au, "
110         COMMON_VIDEO_CAPS "; "
111         "video/x-divx, "
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 "; "
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-vp9, "
132         COMMON_VIDEO_CAPS "; "
133         "video/x-raw, "
134         "format = (string) { YUY2, I420, YV12, UYVY, AYUV, GRAY8, BGR, RGB }, "
135         COMMON_VIDEO_CAPS "; "
136         "video/x-prores, "
137         COMMON_VIDEO_CAPS "; "
138         "video/x-wmv, " "wmvversion = (int) [ 1, 3 ], " COMMON_VIDEO_CAPS)
139     );
140
141 #define COMMON_AUDIO_CAPS \
142   "channels = (int) [ 1, MAX ], " \
143   "rate = (int) [ 1, MAX ]"
144
145 /* FIXME:
146  * * require codec data, etc as needed
147  */
148 static GstStaticPadTemplate audiosink_templ =
149     GST_STATIC_PAD_TEMPLATE ("audio_%u",
150     GST_PAD_SINK,
151     GST_PAD_REQUEST,
152     GST_STATIC_CAPS ("audio/mpeg, "
153         "mpegversion = (int) 1, "
154         "layer = (int) [ 1, 3 ], "
155         COMMON_AUDIO_CAPS "; "
156         "audio/mpeg, "
157         "mpegversion = (int) { 2, 4 }, "
158         "stream-format = (string) raw, "
159         COMMON_AUDIO_CAPS "; "
160         "audio/x-ac3, "
161         COMMON_AUDIO_CAPS "; "
162         "audio/x-eac3, "
163         COMMON_AUDIO_CAPS "; "
164         "audio/x-dts, "
165         COMMON_AUDIO_CAPS "; "
166         "audio/x-vorbis, "
167         COMMON_AUDIO_CAPS "; "
168         "audio/x-flac, "
169         COMMON_AUDIO_CAPS "; "
170         "audio/x-opus; "
171         "audio/x-speex, "
172         COMMON_AUDIO_CAPS "; "
173         "audio/x-raw, "
174         "format = (string) { U8, S16BE, S16LE, S24BE, S24LE, S32BE, S32LE, F32LE, F64LE }, "
175         "layout = (string) interleaved, "
176         COMMON_AUDIO_CAPS ";"
177         "audio/x-tta, "
178         "width = (int) { 8, 16, 24 }, "
179         "channels = (int) { 1, 2 }, " "rate = (int) [ 8000, 96000 ]; "
180         "audio/x-pn-realaudio, "
181         "raversion = (int) { 1, 2, 8 }, " COMMON_AUDIO_CAPS "; "
182         "audio/x-wma, " "wmaversion = (int) [ 1, 3 ], "
183         "block_align = (int) [ 0, 65535 ], bitrate = (int) [ 0, 524288 ], "
184         COMMON_AUDIO_CAPS ";"
185         "audio/x-alaw, "
186         "channels = (int) {1, 2}, " "rate = (int) [ 8000, 192000 ]; "
187         "audio/x-mulaw, "
188         "channels = (int) {1, 2}, " "rate = (int) [ 8000, 192000 ]; "
189         "audio/x-adpcm, "
190         "layout = (string)dvi, "
191         "block_align = (int)[64, 8192], "
192         "channels = (int) { 1, 2 }, " "rate = (int) [ 8000, 96000 ]; "
193         "audio/x-adpcm, "
194         "layout = (string)g726, " "channels = (int)1," "rate = (int)8000; ")
195     );
196
197 static GstStaticPadTemplate subtitlesink_templ =
198     GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
199     GST_PAD_SINK,
200     GST_PAD_REQUEST,
201     GST_STATIC_CAPS ("subtitle/x-kate; "
202         "text/x-raw, format=utf8; application/x-ssa; application/x-ass; "
203         "application/x-usf; subpicture/x-dvd; "
204         "application/x-subtitle-unknown")
205     );
206
207 static gpointer parent_class;   /* NULL */
208
209 /* Matroska muxer destructor */
210 static void gst_matroska_mux_class_init (GstMatroskaMuxClass * klass);
211 static void gst_matroska_mux_init (GstMatroskaMux * mux, gpointer g_class);
212 static void gst_matroska_mux_finalize (GObject * object);
213
214 /* Pads collected callback */
215 static GstFlowReturn gst_matroska_mux_handle_buffer (GstCollectPads * pads,
216     GstCollectData * data, GstBuffer * buf, gpointer user_data);
217 static gboolean gst_matroska_mux_handle_sink_event (GstCollectPads * pads,
218     GstCollectData * data, GstEvent * event, gpointer user_data);
219
220 /* pad functions */
221 static gboolean gst_matroska_mux_handle_src_event (GstPad * pad,
222     GstObject * parent, GstEvent * event);
223 static GstPad *gst_matroska_mux_request_new_pad (GstElement * element,
224     GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
225 static void gst_matroska_mux_release_pad (GstElement * element, GstPad * pad);
226
227 /* gst internal change state handler */
228 static GstStateChangeReturn
229 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition);
230
231 /* gobject bla bla */
232 static void gst_matroska_mux_set_property (GObject * object,
233     guint prop_id, const GValue * value, GParamSpec * pspec);
234 static void gst_matroska_mux_get_property (GObject * object,
235     guint prop_id, GValue * value, GParamSpec * pspec);
236
237 /* reset muxer */
238 static void gst_matroska_mux_reset (GstElement * element);
239
240 /* uid generation */
241 static guint64 gst_matroska_mux_create_uid (GstMatroskaMux * mux);
242
243 static gboolean theora_streamheader_to_codecdata (const GValue * streamheader,
244     GstMatroskaTrackContext * context);
245 static gboolean vorbis_streamheader_to_codecdata (const GValue * streamheader,
246     GstMatroskaTrackContext * context);
247 static gboolean speex_streamheader_to_codecdata (const GValue * streamheader,
248     GstMatroskaTrackContext * context);
249 static gboolean kate_streamheader_to_codecdata (const GValue * streamheader,
250     GstMatroskaTrackContext * context);
251 static gboolean flac_streamheader_to_codecdata (const GValue * streamheader,
252     GstMatroskaTrackContext * context);
253 static void
254 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
255     gpointer data);
256 static gboolean gst_matroska_mux_tag_list_is_empty (const GstTagList * list);
257 static void gst_matroska_mux_write_streams_tags (GstMatroskaMux * mux);
258 static gboolean gst_matroska_mux_streams_have_tags (GstMatroskaMux * mux);
259
260 /* Cannot use boilerplate macros here because we need the full init function
261  * signature with the additional class argument, so we use the right template
262  * for the sink caps */
263 GType
264 gst_matroska_mux_get_type (void)
265 {
266   static GType object_type;     /* 0 */
267
268   if (object_type == 0) {
269     static const GTypeInfo object_info = {
270       sizeof (GstMatroskaMuxClass),
271       NULL,                     /* base_init */
272       NULL,                     /* base_finalize */
273       (GClassInitFunc) gst_matroska_mux_class_init,
274       NULL,                     /* class_finalize */
275       NULL,                     /* class_data */
276       sizeof (GstMatroskaMux),
277       0,                        /* n_preallocs */
278       (GInstanceInitFunc) gst_matroska_mux_init
279     };
280     const GInterfaceInfo iface_info = { NULL };
281
282     object_type = g_type_register_static (GST_TYPE_ELEMENT,
283         "GstMatroskaMux", &object_info, (GTypeFlags) 0);
284
285     g_type_add_interface_static (object_type, GST_TYPE_TAG_SETTER, &iface_info);
286     g_type_add_interface_static (object_type, GST_TYPE_TOC_SETTER, &iface_info);
287   }
288
289   return object_type;
290 }
291
292 static void
293 gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
294 {
295   GObjectClass *gobject_class;
296   GstElementClass *gstelement_class;
297
298   gobject_class = (GObjectClass *) klass;
299   gstelement_class = (GstElementClass *) klass;
300
301   gst_element_class_add_static_pad_template (gstelement_class,
302       &videosink_templ);
303   gst_element_class_add_static_pad_template (gstelement_class,
304       &audiosink_templ);
305   gst_element_class_add_static_pad_template (gstelement_class,
306       &subtitlesink_templ);
307   gst_element_class_add_static_pad_template (gstelement_class, &src_templ);
308   gst_element_class_set_static_metadata (gstelement_class, "Matroska muxer",
309       "Codec/Muxer",
310       "Muxes video/audio/subtitle streams into a matroska stream",
311       "GStreamer maintainers <gstreamer-devel@lists.freedesktop.org>");
312
313   GST_DEBUG_CATEGORY_INIT (matroskamux_debug, "matroskamux", 0,
314       "Matroska muxer");
315
316   gobject_class->finalize = gst_matroska_mux_finalize;
317
318   gobject_class->get_property = gst_matroska_mux_get_property;
319   gobject_class->set_property = gst_matroska_mux_set_property;
320
321   g_object_class_install_property (gobject_class, PROP_WRITING_APP,
322       g_param_spec_string ("writing-app", "Writing application.",
323           "The name the application that creates the matroska file.",
324           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
325   g_object_class_install_property (gobject_class, PROP_DOCTYPE_VERSION,
326       g_param_spec_int ("version", "DocType version",
327           "This parameter determines what Matroska features can be used.",
328           1, 2, DEFAULT_DOCTYPE_VERSION,
329           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
330   g_object_class_install_property (gobject_class, PROP_MIN_INDEX_INTERVAL,
331       g_param_spec_int64 ("min-index-interval", "Minimum time between index "
332           "entries", "An index entry is created every so many nanoseconds.",
333           0, G_MAXINT64, DEFAULT_MIN_INDEX_INTERVAL,
334           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
335   g_object_class_install_property (gobject_class, PROP_STREAMABLE,
336       g_param_spec_boolean ("streamable", "Determines whether output should "
337           "be streamable", "If set to true, the output should be as if it is "
338           "to be streamed and hence no indexes written or duration written.",
339           DEFAULT_STREAMABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
340   g_object_class_install_property (gobject_class, PROP_TIMECODESCALE,
341       g_param_spec_int64 ("timecodescale", "Timecode Scale",
342           "TimecodeScale used to calculate the Raw Timecode of a Block", 1,
343           GST_SECOND, DEFAULT_TIMECODESCALE,
344           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
345
346   gstelement_class->change_state =
347       GST_DEBUG_FUNCPTR (gst_matroska_mux_change_state);
348   gstelement_class->request_new_pad =
349       GST_DEBUG_FUNCPTR (gst_matroska_mux_request_new_pad);
350   gstelement_class->release_pad =
351       GST_DEBUG_FUNCPTR (gst_matroska_mux_release_pad);
352
353   parent_class = g_type_class_peek_parent (klass);
354 }
355
356 /*
357  * Start of pad option handler code
358  */
359 #define DEFAULT_PAD_FRAME_DURATION TRUE
360 #define DEFAULT_PAD_FRAME_DURATION_VP8 FALSE
361
362 enum
363 {
364   PROP_PAD_0,
365   PROP_PAD_FRAME_DURATION
366 };
367
368 typedef struct
369 {
370   GstPad parent;
371   gboolean frame_duration;
372   gboolean frame_duration_user;
373 } GstMatroskamuxPad;
374
375 typedef GstPadClass GstMatroskamuxPadClass;
376
377 GType gst_matroskamux_pad_get_type (void);
378 G_DEFINE_TYPE (GstMatroskamuxPad, gst_matroskamux_pad, GST_TYPE_PAD);
379
380 #define GST_TYPE_MATROSKAMUX_PAD (gst_matroskamux_pad_get_type())
381 #define GST_MATROSKAMUX_PAD(pad) (G_TYPE_CHECK_INSTANCE_CAST((pad),GST_TYPE_MATROSKAMUX_PAD,GstMatroskamuxPad))
382 #define GST_MATROSKAMUX_PAD_CAST(pad) ((GstMatroskamuxPad *) pad)
383 #define GST_IS_MATROSKAMUX_PAD(pad) (G_TYPE_CHECK_INSTANCE_TYPE((pad),GST_TYPE_MATROSKAMUX_PAD))
384
385 static void
386 gst_matroskamux_pad_get_property (GObject * object, guint prop_id,
387     GValue * value, GParamSpec * pspec)
388 {
389   GstMatroskamuxPad *pad = GST_MATROSKAMUX_PAD (object);
390
391   switch (prop_id) {
392     case PROP_PAD_FRAME_DURATION:
393       g_value_set_boolean (value, pad->frame_duration);
394       break;
395     default:
396       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
397       break;
398   }
399 }
400
401 static void
402 gst_matroskamux_pad_set_property (GObject * object, guint prop_id,
403     const GValue * value, GParamSpec * pspec)
404 {
405   GstMatroskamuxPad *pad = GST_MATROSKAMUX_PAD (object);
406
407   switch (prop_id) {
408     case PROP_PAD_FRAME_DURATION:
409       pad->frame_duration = g_value_get_boolean (value);
410       pad->frame_duration_user = TRUE;
411       break;
412     default:
413       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
414       break;
415   }
416 }
417
418 static void
419 gst_matroskamux_pad_class_init (GstMatroskamuxPadClass * klass)
420 {
421   GObjectClass *gobject_class = (GObjectClass *) klass;
422
423   gobject_class->set_property = gst_matroskamux_pad_set_property;
424   gobject_class->get_property = gst_matroskamux_pad_get_property;
425
426   g_object_class_install_property (gobject_class, PROP_PAD_FRAME_DURATION,
427       g_param_spec_boolean ("frame-duration", "Frame duration",
428           "Default frame duration", DEFAULT_PAD_FRAME_DURATION,
429           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
430 }
431
432 static void
433 gst_matroskamux_pad_init (GstMatroskamuxPad * pad)
434 {
435   pad->frame_duration = DEFAULT_PAD_FRAME_DURATION;
436   pad->frame_duration_user = FALSE;
437 }
438
439 /*
440  * End of pad option handler code
441  **/
442
443 static void
444 gst_matroska_mux_init (GstMatroskaMux * mux, gpointer g_class)
445 {
446   GstPadTemplate *templ;
447
448   templ =
449       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
450   mux->srcpad = gst_pad_new_from_template (templ, "src");
451
452   gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event);
453   gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
454   gst_pad_use_fixed_caps (mux->srcpad);
455
456   mux->collect = gst_collect_pads_new ();
457   gst_collect_pads_set_clip_function (mux->collect,
458       GST_DEBUG_FUNCPTR (gst_collect_pads_clip_running_time), mux);
459   gst_collect_pads_set_buffer_function (mux->collect,
460       GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_buffer), mux);
461   gst_collect_pads_set_event_function (mux->collect,
462       GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event), mux);
463
464   mux->ebml_write = gst_ebml_write_new (mux->srcpad);
465   mux->doctype = GST_MATROSKA_DOCTYPE_MATROSKA;
466
467   /* property defaults */
468   mux->doctype_version = DEFAULT_DOCTYPE_VERSION;
469   mux->writing_app = g_strdup (DEFAULT_WRITING_APP);
470   mux->min_index_interval = DEFAULT_MIN_INDEX_INTERVAL;
471   mux->ebml_write->streamable = DEFAULT_STREAMABLE;
472   mux->time_scale = DEFAULT_TIMECODESCALE;
473
474   /* initialize internal variables */
475   mux->index = NULL;
476   mux->num_streams = 0;
477   mux->num_a_streams = 0;
478   mux->num_t_streams = 0;
479   mux->num_v_streams = 0;
480
481   /* create used uid list */
482   mux->used_uids = g_array_sized_new (FALSE, FALSE, sizeof (guint64), 10);
483
484   /* initialize remaining variables */
485   gst_matroska_mux_reset (GST_ELEMENT (mux));
486 }
487
488
489 /**
490  * gst_matroska_mux_finalize:
491  * @object: #GstMatroskaMux that should be finalized.
492  *
493  * Finalize matroska muxer.
494  */
495 static void
496 gst_matroska_mux_finalize (GObject * object)
497 {
498   GstMatroskaMux *mux = GST_MATROSKA_MUX (object);
499
500   gst_event_replace (&mux->force_key_unit_event, NULL);
501
502   gst_object_unref (mux->collect);
503   gst_object_unref (mux->ebml_write);
504   g_free (mux->writing_app);
505
506   g_array_free (mux->used_uids, TRUE);
507
508   G_OBJECT_CLASS (parent_class)->finalize (object);
509 }
510
511
512 /**
513  * gst_matroska_mux_create_uid:
514  * @mux: #GstMatroskaMux to generate UID for.
515  *
516  * Generate new unused track UID.
517  *
518  * Returns: New track UID.
519  */
520 static guint64
521 gst_matroska_mux_create_uid (GstMatroskaMux * mux)
522 {
523   guint64 uid = 0;
524
525   while (!uid) {
526     guint i;
527
528     uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
529     for (i = 0; i < mux->used_uids->len; i++) {
530       if (g_array_index (mux->used_uids, guint64, i) == uid) {
531         uid = 0;
532         break;
533       }
534     }
535     g_array_append_val (mux->used_uids, uid);
536   }
537
538   return uid;
539 }
540
541
542 /**
543  * gst_matroska_pad_reset:
544  * @collect_pad: the #GstMatroskaPad
545  *
546  * Reset and/or release resources of a matroska collect pad.
547  */
548 static void
549 gst_matroska_pad_reset (GstMatroskaPad * collect_pad, gboolean full)
550 {
551   gchar *name = NULL;
552   GstMatroskaTrackType type = 0;
553
554   /* free track information */
555   if (collect_pad->track != NULL) {
556     /* retrieve for optional later use */
557     name = collect_pad->track->name;
558     type = collect_pad->track->type;
559     /* extra for video */
560     if (type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
561       GstMatroskaTrackVideoContext *ctx =
562           (GstMatroskaTrackVideoContext *) collect_pad->track;
563
564       if (ctx->dirac_unit) {
565         gst_buffer_unref (ctx->dirac_unit);
566         ctx->dirac_unit = NULL;
567       }
568     }
569     g_free (collect_pad->track->codec_id);
570     g_free (collect_pad->track->codec_name);
571     if (full)
572       g_free (collect_pad->track->name);
573     g_free (collect_pad->track->language);
574     g_free (collect_pad->track->codec_priv);
575     g_free (collect_pad->track);
576     collect_pad->track = NULL;
577     if (collect_pad->tags) {
578       gst_tag_list_unref (collect_pad->tags);
579       collect_pad->tags = NULL;
580     }
581   }
582
583   if (!full && type != 0) {
584     GstMatroskaTrackContext *context;
585
586     /* create a fresh context */
587     switch (type) {
588       case GST_MATROSKA_TRACK_TYPE_VIDEO:
589         context = (GstMatroskaTrackContext *)
590             g_new0 (GstMatroskaTrackVideoContext, 1);
591         break;
592       case GST_MATROSKA_TRACK_TYPE_AUDIO:
593         context = (GstMatroskaTrackContext *)
594             g_new0 (GstMatroskaTrackAudioContext, 1);
595         break;
596       case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
597         context = (GstMatroskaTrackContext *)
598             g_new0 (GstMatroskaTrackSubtitleContext, 1);
599         break;
600       default:
601         g_assert_not_reached ();
602         return;
603     }
604
605     context->type = type;
606     context->name = name;
607     context->uid = gst_matroska_mux_create_uid (collect_pad->mux);
608     /* TODO: check default values for the context */
609     context->flags = GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT;
610     collect_pad->track = context;
611     collect_pad->start_ts = GST_CLOCK_TIME_NONE;
612     collect_pad->end_ts = GST_CLOCK_TIME_NONE;
613     collect_pad->tags = gst_tag_list_new_empty ();
614     gst_tag_list_set_scope (collect_pad->tags, GST_TAG_SCOPE_STREAM);
615   }
616 }
617
618 /**
619  * gst_matroska_pad_free:
620  * @collect_pad: the #GstMatroskaPad
621  *
622  * Release resources of a matroska collect pad.
623  */
624 static void
625 gst_matroska_pad_free (GstPad * collect_pad)
626 {
627   gst_matroska_pad_reset ((GstMatroskaPad *) collect_pad, TRUE);
628 }
629
630
631 /**
632  * gst_matroska_mux_reset:
633  * @element: #GstMatroskaMux that should be reseted.
634  *
635  * Reset matroska muxer back to initial state.
636  */
637 static void
638 gst_matroska_mux_reset (GstElement * element)
639 {
640   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
641   GSList *walk;
642
643   /* reset EBML write */
644   gst_ebml_write_reset (mux->ebml_write);
645
646   /* reset input */
647   mux->state = GST_MATROSKA_MUX_STATE_START;
648
649   /* clean up existing streams */
650
651   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
652     GstMatroskaPad *collect_pad;
653
654     collect_pad = (GstMatroskaPad *) walk->data;
655
656     /* reset collect pad to pristine state */
657     gst_matroska_pad_reset (collect_pad, FALSE);
658   }
659
660   /* reset indexes */
661   mux->num_indexes = 0;
662   g_free (mux->index);
663   mux->index = NULL;
664
665   /* reset timers */
666   mux->max_cluster_duration = G_MAXINT16 * mux->time_scale;
667   mux->duration = 0;
668
669   /* reset cluster */
670   mux->cluster = 0;
671   mux->cluster_time = 0;
672   mux->cluster_pos = 0;
673   mux->prev_cluster_size = 0;
674
675   /* reset tags */
676   gst_tag_setter_reset_tags (GST_TAG_SETTER (mux));
677
678   mux->tags_pos = 0;
679
680   /* reset chapters */
681   gst_toc_setter_reset (GST_TOC_SETTER (mux));
682
683   mux->chapters_pos = 0;
684
685   /* clear used uids */
686   if (mux->used_uids->len > 0) {
687     g_array_remove_range (mux->used_uids, 0, mux->used_uids->len);
688   }
689 }
690
691 /**
692  * gst_matroska_mux_handle_src_event:
693  * @pad: Pad which received the event.
694  * @event: Received event.
695  *
696  * handle events - copied from oggmux without understanding
697  *
698  * Returns: #TRUE on success.
699  */
700 static gboolean
701 gst_matroska_mux_handle_src_event (GstPad * pad, GstObject * parent,
702     GstEvent * event)
703 {
704   GstEventType type;
705
706   type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
707
708   switch (type) {
709     case GST_EVENT_SEEK:
710       /* disable seeking for now */
711       return FALSE;
712     default:
713       break;
714   }
715
716   return gst_pad_event_default (pad, parent, event);
717 }
718
719
720 static void
721 gst_matroska_mux_free_codec_priv (GstMatroskaTrackContext * context)
722 {
723   if (context->codec_priv != NULL) {
724     g_free (context->codec_priv);
725     context->codec_priv = NULL;
726     context->codec_priv_size = 0;
727   }
728 }
729
730 static void
731 gst_matroska_mux_build_vobsub_private (GstMatroskaTrackContext * context,
732     const guint * clut)
733 {
734   gchar *clutv[17];
735   gchar *sclut;
736   gint i;
737   guint32 col;
738   gdouble y, u, v;
739   guint8 r, g, b;
740
741   /* produce comma-separated list in hex format */
742   for (i = 0; i < 16; ++i) {
743     col = clut[i];
744     /* replicate vobsub's slightly off RGB conversion calculation */
745     y = (((col >> 16) & 0xff) - 16) * 255 / 219;
746     u = ((col >> 8) & 0xff) - 128;
747     v = (col & 0xff) - 128;
748     r = CLAMP (1.0 * y + 1.4022 * u, 0, 255);
749     g = CLAMP (1.0 * y - 0.3456 * u - 0.7145 * v, 0, 255);
750     b = CLAMP (1.0 * y + 1.7710 * v, 0, 255);
751     clutv[i] = g_strdup_printf ("%02x%02x%02x", r, g, b);
752   }
753   clutv[i] = NULL;
754   sclut = g_strjoinv (",", clutv);
755
756   /* build codec private; only palette for now */
757   gst_matroska_mux_free_codec_priv (context);
758   context->codec_priv = (guint8 *) g_strdup_printf ("palette: %s", sclut);
759   /* include terminating 0 */
760   context->codec_priv_size = strlen ((gchar *) context->codec_priv) + 1;
761   g_free (sclut);
762   for (i = 0; i < 16; ++i) {
763     g_free (clutv[i]);
764   }
765 }
766
767
768 /**
769  * gst_matroska_mux_handle_sink_event:
770  * @pad: Pad which received the event.
771  * @event: Received event.
772  *
773  * handle events - informational ones like tags
774  *
775  * Returns: #TRUE on success.
776  */
777 static gboolean
778 gst_matroska_mux_handle_sink_event (GstCollectPads * pads,
779     GstCollectData * data, GstEvent * event, gpointer user_data)
780 {
781   GstMatroskaPad *collect_pad;
782   GstMatroskaTrackContext *context;
783   GstMatroskaMux *mux;
784   GstPad *pad;
785   GstTagList *list;
786   gboolean ret = TRUE;
787
788   mux = GST_MATROSKA_MUX (user_data);
789   collect_pad = (GstMatroskaPad *) data;
790   pad = data->pad;
791   context = collect_pad->track;
792   g_assert (context);
793
794   switch (GST_EVENT_TYPE (event)) {
795     case GST_EVENT_CAPS:{
796       GstCaps *caps;
797
798       collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
799       gst_event_parse_caps (event, &caps);
800
801       ret = collect_pad->capsfunc (pad, caps);
802       gst_event_unref (event);
803       event = NULL;
804       break;
805     }
806     case GST_EVENT_TAG:{
807       gchar *lang = NULL;
808
809       GST_DEBUG_OBJECT (mux, "received tag event");
810       gst_event_parse_tag (event, &list);
811
812       /* Matroska wants ISO 639-2B code, taglist most likely contains 639-1 */
813       if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) {
814         const gchar *lang_code;
815
816         lang_code = gst_tag_get_language_code_iso_639_2B (lang);
817         if (lang_code) {
818           GST_INFO_OBJECT (pad, "Setting language to '%s'", lang_code);
819           g_free (context->language);
820           context->language = g_strdup (lang_code);
821         } else {
822           GST_WARNING_OBJECT (pad, "Did not get language code for '%s'", lang);
823         }
824         g_free (lang);
825       }
826
827       /* FIXME: what about stream-specific tags? */
828       if (gst_tag_list_get_scope (list) == GST_TAG_SCOPE_GLOBAL) {
829         gst_tag_setter_merge_tags (GST_TAG_SETTER (mux), list,
830             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (mux)));
831       } else {
832         gst_tag_list_insert (collect_pad->tags, list, GST_TAG_MERGE_REPLACE);
833       }
834
835       gst_event_unref (event);
836       /* handled this, don't want collectpads to forward it downstream */
837       event = NULL;
838       ret = TRUE;
839       break;
840     }
841     case GST_EVENT_TOC:{
842       GstToc *toc, *old_toc;
843
844       if (mux->chapters_pos > 0)
845         break;
846
847       GST_DEBUG_OBJECT (mux, "received toc event");
848       gst_event_parse_toc (event, &toc, NULL);
849
850       if (toc != NULL) {
851         old_toc = gst_toc_setter_get_toc (GST_TOC_SETTER (mux));
852         if (old_toc != NULL) {
853           if (old_toc != toc)
854             GST_INFO_OBJECT (pad, "Replacing TOC with a new one");
855           gst_toc_unref (old_toc);
856         }
857
858         gst_toc_setter_set_toc (GST_TOC_SETTER (mux), toc);
859         gst_toc_unref (toc);
860       }
861
862       gst_event_unref (event);
863       /* handled this, don't want collectpads to forward it downstream */
864       event = NULL;
865       break;
866     }
867     case GST_EVENT_CUSTOM_DOWNSTREAM:
868     case GST_EVENT_CUSTOM_DOWNSTREAM_STICKY:{
869       const GstStructure *structure;
870
871       structure = gst_event_get_structure (event);
872       if (gst_structure_has_name (structure, "GstForceKeyUnit")) {
873         gst_event_replace (&mux->force_key_unit_event, NULL);
874         mux->force_key_unit_event = event;
875         event = NULL;
876       } else if (gst_structure_has_name (structure, "application/x-gst-dvd") &&
877           !strcmp ("dvd-spu-clut-change",
878               gst_structure_get_string (structure, "event"))) {
879         gchar name[16];
880         gint i, value;
881         guint clut[16];
882
883         GST_DEBUG_OBJECT (pad, "New DVD colour table received");
884         if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE) {
885           GST_DEBUG_OBJECT (pad, "... discarding");
886           break;
887         }
888         /* first transform event data into table form */
889         for (i = 0; i < 16; i++) {
890           g_snprintf (name, sizeof (name), "clut%02d", i);
891           if (!gst_structure_get_int (structure, name, &value)) {
892             GST_ERROR_OBJECT (mux, "dvd-spu-clut-change event did not "
893                 "contain %s field", name);
894             goto break_hard;
895           }
896           clut[i] = value;
897         }
898
899         /* transform into private data for stream; text form */
900         gst_matroska_mux_build_vobsub_private (context, clut);
901       }
902     }
903       /* fall through */
904     default:
905       break;
906   }
907
908 break_hard:
909   if (event != NULL)
910     return gst_collect_pads_event_default (pads, data, event, FALSE);
911
912   return ret;
913 }
914
915 static void
916 gst_matroska_mux_set_codec_id (GstMatroskaTrackContext * context,
917     const char *id)
918 {
919   g_assert (context && id);
920   g_free (context->codec_id);
921   context->codec_id = g_strdup (id);
922 }
923
924 /**
925  * gst_matroska_mux_video_pad_setcaps:
926  * @pad: Pad which got the caps.
927  * @caps: New caps.
928  *
929  * Setcaps function for video sink pad.
930  *
931  * Returns: #TRUE on success.
932  */
933 static gboolean
934 gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
935 {
936   GstMatroskaTrackContext *context = NULL;
937   GstMatroskaTrackVideoContext *videocontext;
938   GstMatroskaMux *mux;
939   GstMatroskaPad *collect_pad;
940   GstStructure *structure;
941   const gchar *mimetype;
942   const gchar *interlace_mode, *s;
943   const GValue *value = NULL;
944   GstBuffer *codec_buf = NULL;
945   gint width, height, pixel_width, pixel_height;
946   gint fps_d, fps_n;
947
948   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
949
950   /* find context */
951   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
952   g_assert (collect_pad);
953   context = collect_pad->track;
954   g_assert (context);
955   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO);
956   videocontext = (GstMatroskaTrackVideoContext *) context;
957
958   /* gst -> matroska ID'ing */
959   structure = gst_caps_get_structure (caps, 0);
960
961   mimetype = gst_structure_get_name (structure);
962
963   interlace_mode = gst_structure_get_string (structure, "interlace-mode");
964   if (interlace_mode != NULL && strcmp (interlace_mode, "progressive") != 0)
965     context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
966
967   if (!strcmp (mimetype, "video/x-theora")) {
968     /* we'll extract the details later from the theora identification header */
969     goto skip_details;
970   }
971
972   /* get general properties */
973   /* spec says it is mandatory */
974   if (!gst_structure_get_int (structure, "width", &width) ||
975       !gst_structure_get_int (structure, "height", &height))
976     goto refuse_caps;
977
978   videocontext->pixel_width = width;
979   videocontext->pixel_height = height;
980
981   /* set vp8 defaults or let user override it */
982   if (GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration_user == FALSE
983       && (!strcmp (mimetype, "video/x-vp8")
984           || !strcmp (mimetype, "video/x-vp9")))
985     GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration =
986         DEFAULT_PAD_FRAME_DURATION_VP8;
987
988   if (GST_MATROSKAMUX_PAD_CAST (pad)->frame_duration
989       && gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)
990       && fps_n > 0) {
991     context->default_duration =
992         gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
993     GST_LOG_OBJECT (pad, "default duration = %" GST_TIME_FORMAT,
994         GST_TIME_ARGS (context->default_duration));
995   } else {
996     context->default_duration = 0;
997   }
998   if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
999           &pixel_width, &pixel_height)) {
1000     if (pixel_width > pixel_height) {
1001       videocontext->display_width = width * pixel_width / pixel_height;
1002       videocontext->display_height = height;
1003     } else if (pixel_width < pixel_height) {
1004       videocontext->display_width = width;
1005       videocontext->display_height = height * pixel_height / pixel_width;
1006     } else {
1007       videocontext->display_width = 0;
1008       videocontext->display_height = 0;
1009     }
1010   } else {
1011     videocontext->display_width = 0;
1012     videocontext->display_height = 0;
1013   }
1014
1015   /* Collect stereoscopic info, if any */
1016   if ((s = gst_structure_get_string (structure, "multiview-mode")))
1017     videocontext->multiview_mode =
1018         gst_video_multiview_mode_from_caps_string (s);
1019   gst_structure_get_flagset (structure, "multiview-flags",
1020       &videocontext->multiview_flags, NULL);
1021
1022
1023 skip_details:
1024
1025   videocontext->asr_mode = GST_MATROSKA_ASPECT_RATIO_MODE_FREE;
1026   videocontext->fourcc = 0;
1027
1028   /* TODO: - check if we handle all codecs by the spec, i.e. codec private
1029    *         data and other settings
1030    *       - add new formats
1031    */
1032
1033   /* extract codec_data, may turn out needed */
1034   value = gst_structure_get_value (structure, "codec_data");
1035   if (value)
1036     codec_buf = (GstBuffer *) gst_value_get_buffer (value);
1037
1038   /* find type */
1039   if (!strcmp (mimetype, "video/x-raw")) {
1040     const gchar *fstr;
1041     gst_matroska_mux_set_codec_id (context,
1042         GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
1043     fstr = gst_structure_get_string (structure, "format");
1044     if (fstr) {
1045       if (strlen (fstr) == 4)
1046         videocontext->fourcc = GST_STR_FOURCC (fstr);
1047       else if (!strcmp (fstr, "GRAY8"))
1048         videocontext->fourcc = GST_MAKE_FOURCC ('Y', '8', '0', '0');
1049       else if (!strcmp (fstr, "BGR"))
1050         videocontext->fourcc = GST_MAKE_FOURCC ('B', 'G', 'R', 24);
1051       else if (!strcmp (fstr, "RGB"))
1052         videocontext->fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', 24);
1053     }
1054   } else if (!strcmp (mimetype, "video/x-huffyuv")      /* MS/VfW compatibility cases */
1055       ||!strcmp (mimetype, "video/x-divx")
1056       || !strcmp (mimetype, "video/x-dv")
1057       || !strcmp (mimetype, "video/x-h263")
1058       || !strcmp (mimetype, "video/x-msmpeg")
1059       || !strcmp (mimetype, "video/x-wmv")
1060       || !strcmp (mimetype, "image/jpeg")) {
1061     gst_riff_strf_vids *bih;
1062     gint size = sizeof (gst_riff_strf_vids);
1063     guint32 fourcc = 0;
1064
1065     if (!strcmp (mimetype, "video/x-huffyuv"))
1066       fourcc = GST_MAKE_FOURCC ('H', 'F', 'Y', 'U');
1067     else if (!strcmp (mimetype, "video/x-dv"))
1068       fourcc = GST_MAKE_FOURCC ('D', 'V', 'S', 'D');
1069     else if (!strcmp (mimetype, "video/x-h263"))
1070       fourcc = GST_MAKE_FOURCC ('H', '2', '6', '3');
1071     else if (!strcmp (mimetype, "video/x-divx")) {
1072       gint divxversion;
1073
1074       gst_structure_get_int (structure, "divxversion", &divxversion);
1075       switch (divxversion) {
1076         case 3:
1077           fourcc = GST_MAKE_FOURCC ('D', 'I', 'V', '3');
1078           break;
1079         case 4:
1080           fourcc = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
1081           break;
1082         case 5:
1083           fourcc = GST_MAKE_FOURCC ('D', 'X', '5', '0');
1084           break;
1085       }
1086     } else if (!strcmp (mimetype, "video/x-msmpeg")) {
1087       gint msmpegversion;
1088
1089       gst_structure_get_int (structure, "msmpegversion", &msmpegversion);
1090       switch (msmpegversion) {
1091         case 41:
1092           fourcc = GST_MAKE_FOURCC ('M', 'P', 'G', '4');
1093           break;
1094         case 42:
1095           fourcc = GST_MAKE_FOURCC ('M', 'P', '4', '2');
1096           break;
1097         case 43:
1098           goto msmpeg43;
1099           break;
1100       }
1101     } else if (!strcmp (mimetype, "video/x-wmv")) {
1102       gint wmvversion;
1103       const gchar *fstr;
1104
1105       fstr = gst_structure_get_string (structure, "format");
1106       if (fstr && strlen (fstr) == 4) {
1107         fourcc = GST_STR_FOURCC (fstr);
1108       } else if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) {
1109         if (wmvversion == 2) {
1110           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '2');
1111         } else if (wmvversion == 1) {
1112           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '1');
1113         } else if (wmvversion == 3) {
1114           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
1115         }
1116       }
1117     } else if (!strcmp (mimetype, "image/jpeg")) {
1118       fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
1119     }
1120
1121     if (!fourcc)
1122       goto refuse_caps;
1123
1124     bih = g_new0 (gst_riff_strf_vids, 1);
1125     GST_WRITE_UINT32_LE (&bih->size, size);
1126     GST_WRITE_UINT32_LE (&bih->width, videocontext->pixel_width);
1127     GST_WRITE_UINT32_LE (&bih->height, videocontext->pixel_height);
1128     GST_WRITE_UINT32_LE (&bih->compression, fourcc);
1129     GST_WRITE_UINT16_LE (&bih->planes, (guint16) 1);
1130     GST_WRITE_UINT16_LE (&bih->bit_cnt, (guint16) 24);
1131     GST_WRITE_UINT32_LE (&bih->image_size, videocontext->pixel_width *
1132         videocontext->pixel_height * 3);
1133
1134     /* process codec private/initialization data, if any */
1135     if (codec_buf) {
1136       size += gst_buffer_get_size (codec_buf);
1137       bih = g_realloc (bih, size);
1138       GST_WRITE_UINT32_LE (&bih->size, size);
1139       gst_buffer_extract (codec_buf, 0,
1140           (guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
1141     }
1142
1143     gst_matroska_mux_set_codec_id (context,
1144         GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
1145     gst_matroska_mux_free_codec_priv (context);
1146     context->codec_priv = (gpointer) bih;
1147     context->codec_priv_size = size;
1148     context->dts_only = TRUE;
1149   } else if (!strcmp (mimetype, "video/x-h264")) {
1150     gst_matroska_mux_set_codec_id (context,
1151         GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC);
1152     gst_matroska_mux_free_codec_priv (context);
1153     /* Create avcC header */
1154     if (codec_buf != NULL) {
1155       context->codec_priv_size = gst_buffer_get_size (codec_buf);
1156       context->codec_priv = g_malloc0 (context->codec_priv_size);
1157       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
1158     }
1159   } else if (!strcmp (mimetype, "video/x-h265")) {
1160     gst_matroska_mux_set_codec_id (context,
1161         GST_MATROSKA_CODEC_ID_VIDEO_MPEGH_HEVC);
1162     gst_matroska_mux_free_codec_priv (context);
1163     /* Create hvcC header */
1164     if (codec_buf != NULL) {
1165       context->codec_priv_size = gst_buffer_get_size (codec_buf);
1166       context->codec_priv = g_malloc0 (context->codec_priv_size);
1167       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
1168     }
1169   } else if (!strcmp (mimetype, "video/x-theora")) {
1170     const GValue *streamheader;
1171
1172     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_THEORA);
1173
1174     gst_matroska_mux_free_codec_priv (context);
1175
1176     streamheader = gst_structure_get_value (structure, "streamheader");
1177     if (!theora_streamheader_to_codecdata (streamheader, context)) {
1178       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1179           ("theora stream headers missing or malformed"));
1180       goto refuse_caps;
1181     }
1182   } else if (!strcmp (mimetype, "video/x-dirac")) {
1183     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_DIRAC);
1184   } else if (!strcmp (mimetype, "video/x-vp8")) {
1185     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_VP8);
1186   } else if (!strcmp (mimetype, "video/x-vp9")) {
1187     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_VP9);
1188   } else if (!strcmp (mimetype, "video/mpeg")) {
1189     gint mpegversion;
1190
1191     gst_structure_get_int (structure, "mpegversion", &mpegversion);
1192     switch (mpegversion) {
1193       case 1:
1194         gst_matroska_mux_set_codec_id (context,
1195             GST_MATROSKA_CODEC_ID_VIDEO_MPEG1);
1196         break;
1197       case 2:
1198         gst_matroska_mux_set_codec_id (context,
1199             GST_MATROSKA_CODEC_ID_VIDEO_MPEG2);
1200         break;
1201       case 4:
1202         gst_matroska_mux_set_codec_id (context,
1203             GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP);
1204         break;
1205       default:
1206         goto refuse_caps;
1207     }
1208
1209     /* global headers may be in codec data */
1210     if (codec_buf != NULL) {
1211       gst_matroska_mux_free_codec_priv (context);
1212       context->codec_priv_size = gst_buffer_get_size (codec_buf);
1213       context->codec_priv = g_malloc0 (context->codec_priv_size);
1214       gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
1215     }
1216   } else if (!strcmp (mimetype, "video/x-msmpeg")) {
1217   msmpeg43:
1218     /* can only make it here if preceding case verified it was version 3 */
1219     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3);
1220   } else if (!strcmp (mimetype, "video/x-pn-realvideo")) {
1221     gint rmversion;
1222     const GValue *mdpr_data;
1223
1224     gst_structure_get_int (structure, "rmversion", &rmversion);
1225     switch (rmversion) {
1226       case 1:
1227         gst_matroska_mux_set_codec_id (context,
1228             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
1229         break;
1230       case 2:
1231         gst_matroska_mux_set_codec_id (context,
1232             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
1233         break;
1234       case 3:
1235         gst_matroska_mux_set_codec_id (context,
1236             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
1237         break;
1238       case 4:
1239         gst_matroska_mux_set_codec_id (context,
1240             GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
1241         break;
1242       default:
1243         goto refuse_caps;
1244     }
1245
1246     mdpr_data = gst_structure_get_value (structure, "mdpr_data");
1247     if (mdpr_data != NULL) {
1248       guint8 *priv_data = NULL;
1249       guint priv_data_size = 0;
1250
1251       GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
1252
1253       priv_data_size = gst_buffer_get_size (codec_data_buf);
1254       priv_data = g_malloc0 (priv_data_size);
1255
1256       gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
1257
1258       gst_matroska_mux_free_codec_priv (context);
1259       context->codec_priv = priv_data;
1260       context->codec_priv_size = priv_data_size;
1261     }
1262   } else if (strcmp (mimetype, "video/x-prores") == 0) {
1263     const gchar *variant;
1264
1265     gst_matroska_mux_free_codec_priv (context);
1266
1267     variant = gst_structure_get_string (structure, "format");
1268     if (!variant || !g_strcmp0 (variant, "standard"))
1269       context->codec_priv = g_strdup ("apcn");
1270     else if (!g_strcmp0 (variant, "hq"))
1271       context->codec_priv = g_strdup ("apch");
1272     else if (!g_strcmp0 (variant, "lt"))
1273       context->codec_priv = g_strdup ("apcs");
1274     else if (!g_strcmp0 (variant, "proxy"))
1275       context->codec_priv = g_strdup ("apco");
1276     else if (!g_strcmp0 (variant, "4444"))
1277       context->codec_priv = g_strdup ("ap4h");
1278     else {
1279       GST_WARNING_OBJECT (mux, "Unhandled prores format: %s", variant);
1280
1281       goto refuse_caps;
1282     }
1283
1284     context->codec_priv_size = sizeof (guint32);
1285     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_PRORES);
1286   }
1287
1288   return TRUE;
1289
1290   /* ERRORS */
1291 refuse_caps:
1292   {
1293     GST_WARNING_OBJECT (mux, "pad %s refused caps %" GST_PTR_FORMAT,
1294         GST_PAD_NAME (pad), caps);
1295     return FALSE;
1296   }
1297 }
1298
1299 /* N > 0 to expect a particular number of headers, negative if the
1300    number of headers is variable */
1301 static gboolean
1302 xiphN_streamheader_to_codecdata (const GValue * streamheader,
1303     GstMatroskaTrackContext * context, GstBuffer ** p_buf0, int N)
1304 {
1305   GstBuffer **buf = NULL;
1306   GArray *bufarr;
1307   guint8 *priv_data;
1308   guint bufi, i, offset, priv_data_size;
1309
1310   if (streamheader == NULL)
1311     goto no_stream_headers;
1312
1313   if (G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY)
1314     goto wrong_type;
1315
1316   bufarr = g_value_peek_pointer (streamheader);
1317   if (bufarr->len <= 0 || bufarr->len > 255)    /* at least one header, and count stored in a byte */
1318     goto wrong_count;
1319   if (N > 0 && bufarr->len != N)
1320     goto wrong_count;
1321
1322   context->xiph_headers_to_skip = bufarr->len;
1323
1324   buf = (GstBuffer **) g_malloc0 (sizeof (GstBuffer *) * bufarr->len);
1325   for (i = 0; i < bufarr->len; i++) {
1326     GValue *bufval = &g_array_index (bufarr, GValue, i);
1327
1328     if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1329       g_free (buf);
1330       goto wrong_content_type;
1331     }
1332
1333     buf[i] = g_value_peek_pointer (bufval);
1334   }
1335
1336   priv_data_size = 1;
1337   if (bufarr->len > 0) {
1338     for (i = 0; i < bufarr->len - 1; i++) {
1339       priv_data_size += gst_buffer_get_size (buf[i]) / 0xff + 1;
1340     }
1341   }
1342
1343   for (i = 0; i < bufarr->len; ++i) {
1344     priv_data_size += gst_buffer_get_size (buf[i]);
1345   }
1346
1347   priv_data = g_malloc0 (priv_data_size);
1348
1349   priv_data[0] = bufarr->len - 1;
1350   offset = 1;
1351
1352   if (bufarr->len > 0) {
1353     for (bufi = 0; bufi < bufarr->len - 1; bufi++) {
1354       for (i = 0; i < gst_buffer_get_size (buf[bufi]) / 0xff; ++i) {
1355         priv_data[offset++] = 0xff;
1356       }
1357       priv_data[offset++] = gst_buffer_get_size (buf[bufi]) % 0xff;
1358     }
1359   }
1360
1361   for (i = 0; i < bufarr->len; ++i) {
1362     gst_buffer_extract (buf[i], 0, priv_data + offset, -1);
1363     offset += gst_buffer_get_size (buf[i]);
1364   }
1365
1366   gst_matroska_mux_free_codec_priv (context);
1367   context->codec_priv = priv_data;
1368   context->codec_priv_size = priv_data_size;
1369
1370   if (p_buf0)
1371     *p_buf0 = gst_buffer_ref (buf[0]);
1372
1373   g_free (buf);
1374
1375   return TRUE;
1376
1377 /* ERRORS */
1378 no_stream_headers:
1379   {
1380     GST_WARNING ("required streamheaders missing in sink caps!");
1381     return FALSE;
1382   }
1383 wrong_type:
1384   {
1385     GST_WARNING ("streamheaders are not a GST_TYPE_ARRAY, but a %s",
1386         G_VALUE_TYPE_NAME (streamheader));
1387     return FALSE;
1388   }
1389 wrong_count:
1390   {
1391     GST_WARNING ("got %u streamheaders, not %d as expected", bufarr->len, N);
1392     return FALSE;
1393   }
1394 wrong_content_type:
1395   {
1396     GST_WARNING ("streamheaders array does not contain GstBuffers");
1397     return FALSE;
1398   }
1399 }
1400
1401 static gboolean
1402 vorbis_streamheader_to_codecdata (const GValue * streamheader,
1403     GstMatroskaTrackContext * context)
1404 {
1405   GstBuffer *buf0 = NULL;
1406
1407   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
1408     return FALSE;
1409
1410   if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 4) {
1411     GST_WARNING ("First vorbis header too small, ignoring");
1412   } else {
1413     if (gst_buffer_memcmp (buf0, 1, "vorbis", 6) == 0) {
1414       GstMatroskaTrackAudioContext *audiocontext;
1415       GstMapInfo map;
1416       guint8 *hdr;
1417
1418       gst_buffer_map (buf0, &map, GST_MAP_READ);
1419       hdr = map.data + 1 + 6 + 4;
1420       audiocontext = (GstMatroskaTrackAudioContext *) context;
1421       audiocontext->channels = GST_READ_UINT8 (hdr);
1422       audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1);
1423       gst_buffer_unmap (buf0, &map);
1424     }
1425   }
1426
1427   if (buf0)
1428     gst_buffer_unref (buf0);
1429
1430   return TRUE;
1431 }
1432
1433 static gboolean
1434 theora_streamheader_to_codecdata (const GValue * streamheader,
1435     GstMatroskaTrackContext * context)
1436 {
1437   GstBuffer *buf0 = NULL;
1438
1439   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
1440     return FALSE;
1441
1442   if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 26) {
1443     GST_WARNING ("First theora header too small, ignoring");
1444   } else if (gst_buffer_memcmp (buf0, 0, "\200theora\003\002", 9) != 0) {
1445     GST_WARNING ("First header not a theora identification header, ignoring");
1446   } else {
1447     GstMatroskaTrackVideoContext *videocontext;
1448     guint fps_num, fps_denom, par_num, par_denom;
1449     GstMapInfo map;
1450     guint8 *hdr;
1451
1452     gst_buffer_map (buf0, &map, GST_MAP_READ);
1453     hdr = map.data + 1 + 6 + 3 + 2 + 2;
1454
1455     videocontext = (GstMatroskaTrackVideoContext *) context;
1456     videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8;
1457     videocontext->pixel_height = GST_READ_UINT32_BE (hdr + 3) >> 8;
1458     hdr += 3 + 3 + 1 + 1;
1459     fps_num = GST_READ_UINT32_BE (hdr);
1460     fps_denom = GST_READ_UINT32_BE (hdr + 4);
1461     context->default_duration = gst_util_uint64_scale_int (GST_SECOND,
1462         fps_denom, fps_num);
1463     hdr += 4 + 4;
1464     par_num = GST_READ_UINT32_BE (hdr) >> 8;
1465     par_denom = GST_READ_UINT32_BE (hdr + 3) >> 8;
1466     if (par_num > 0 && par_denom > 0) {
1467       if (par_num > par_denom) {
1468         videocontext->display_width =
1469             videocontext->pixel_width * par_num / par_denom;
1470         videocontext->display_height = videocontext->pixel_height;
1471       } else if (par_num < par_denom) {
1472         videocontext->display_width = videocontext->pixel_width;
1473         videocontext->display_height =
1474             videocontext->pixel_height * par_denom / par_num;
1475       } else {
1476         videocontext->display_width = 0;
1477         videocontext->display_height = 0;
1478       }
1479     } else {
1480       videocontext->display_width = 0;
1481       videocontext->display_height = 0;
1482     }
1483
1484     gst_buffer_unmap (buf0, &map);
1485   }
1486
1487   if (buf0)
1488     gst_buffer_unref (buf0);
1489
1490   return TRUE;
1491 }
1492
1493 static gboolean
1494 kate_streamheader_to_codecdata (const GValue * streamheader,
1495     GstMatroskaTrackContext * context)
1496 {
1497   GstBuffer *buf0 = NULL;
1498
1499   if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1))
1500     return FALSE;
1501
1502   if (buf0 == NULL || gst_buffer_get_size (buf0) < 64) {        /* Kate ID header is 64 bytes */
1503     GST_WARNING ("First kate header too small, ignoring");
1504   } else if (gst_buffer_memcmp (buf0, 0, "\200kate\0\0\0", 8) != 0) {
1505     GST_WARNING ("First header not a kate identification header, ignoring");
1506   }
1507
1508   if (buf0)
1509     gst_buffer_unref (buf0);
1510
1511   return TRUE;
1512 }
1513
1514 static gboolean
1515 flac_streamheader_to_codecdata (const GValue * streamheader,
1516     GstMatroskaTrackContext * context)
1517 {
1518   GArray *bufarr;
1519   gint i;
1520   GValue *bufval;
1521   GstBuffer *buffer;
1522
1523   if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
1524     GST_WARNING ("No or invalid streamheader field in the caps");
1525     return FALSE;
1526   }
1527
1528   bufarr = g_value_peek_pointer (streamheader);
1529   if (bufarr->len < 2) {
1530     GST_WARNING ("Too few headers in streamheader field");
1531     return FALSE;
1532   }
1533
1534   context->xiph_headers_to_skip = bufarr->len + 1;
1535
1536   bufval = &g_array_index (bufarr, GValue, 0);
1537   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1538     GST_WARNING ("streamheaders array does not contain GstBuffers");
1539     return FALSE;
1540   }
1541
1542   buffer = g_value_peek_pointer (bufval);
1543
1544   /* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */
1545   if (gst_buffer_get_size (buffer) < 9 + 4 + 4 + 34
1546       || gst_buffer_memcmp (buffer, 1, "FLAC", 4) != 0
1547       || gst_buffer_memcmp (buffer, 9, "fLaC", 4) != 0) {
1548     GST_WARNING ("Invalid streamheader for FLAC");
1549     return FALSE;
1550   }
1551
1552   gst_matroska_mux_free_codec_priv (context);
1553   context->codec_priv_size = gst_buffer_get_size (buffer) - 9;
1554   context->codec_priv = g_malloc (context->codec_priv_size);
1555   gst_buffer_extract (buffer, 9, context->codec_priv, -1);
1556
1557   for (i = 1; i < bufarr->len; i++) {
1558     guint old_size;
1559     bufval = &g_array_index (bufarr, GValue, i);
1560
1561     if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1562       gst_matroska_mux_free_codec_priv (context);
1563       GST_WARNING ("streamheaders array does not contain GstBuffers");
1564       return FALSE;
1565     }
1566
1567     buffer = g_value_peek_pointer (bufval);
1568
1569     old_size = context->codec_priv_size;
1570     context->codec_priv_size += gst_buffer_get_size (buffer);
1571
1572     context->codec_priv = g_realloc (context->codec_priv,
1573         context->codec_priv_size);
1574     gst_buffer_extract (buffer, 0,
1575         (guint8 *) context->codec_priv + old_size, -1);
1576   }
1577
1578   return TRUE;
1579 }
1580
1581 static gboolean
1582 speex_streamheader_to_codecdata (const GValue * streamheader,
1583     GstMatroskaTrackContext * context)
1584 {
1585   GArray *bufarr;
1586   GValue *bufval;
1587   GstBuffer *buffer;
1588   guint old_size;
1589
1590   if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
1591     GST_WARNING ("No or invalid streamheader field in the caps");
1592     return FALSE;
1593   }
1594
1595   bufarr = g_value_peek_pointer (streamheader);
1596   if (bufarr->len != 2) {
1597     GST_WARNING ("Too few headers in streamheader field");
1598     return FALSE;
1599   }
1600
1601   context->xiph_headers_to_skip = bufarr->len + 1;
1602
1603   bufval = &g_array_index (bufarr, GValue, 0);
1604   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1605     GST_WARNING ("streamheaders array does not contain GstBuffers");
1606     return FALSE;
1607   }
1608
1609   buffer = g_value_peek_pointer (bufval);
1610
1611   if (gst_buffer_get_size (buffer) < 80
1612       || gst_buffer_memcmp (buffer, 0, "Speex   ", 8) != 0) {
1613     GST_WARNING ("Invalid streamheader for Speex");
1614     return FALSE;
1615   }
1616
1617   gst_matroska_mux_free_codec_priv (context);
1618   context->codec_priv_size = gst_buffer_get_size (buffer);
1619   context->codec_priv = g_malloc (context->codec_priv_size);
1620   gst_buffer_extract (buffer, 0, context->codec_priv, -1);
1621
1622   bufval = &g_array_index (bufarr, GValue, 1);
1623
1624   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1625     gst_matroska_mux_free_codec_priv (context);
1626     GST_WARNING ("streamheaders array does not contain GstBuffers");
1627     return FALSE;
1628   }
1629
1630   buffer = g_value_peek_pointer (bufval);
1631
1632   old_size = context->codec_priv_size;
1633   context->codec_priv_size += gst_buffer_get_size (buffer);
1634   context->codec_priv = g_realloc (context->codec_priv,
1635       context->codec_priv_size);
1636   gst_buffer_extract (buffer, 0, (guint8 *) context->codec_priv + old_size, -1);
1637
1638   return TRUE;
1639 }
1640
1641 static gboolean
1642 opus_streamheader_to_codecdata (const GValue * streamheader,
1643     GstMatroskaTrackContext * context)
1644 {
1645   GArray *bufarr;
1646   GValue *bufval;
1647   GstBuffer *buf;
1648
1649   if (G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY)
1650     goto wrong_type;
1651
1652   bufarr = g_value_peek_pointer (streamheader);
1653   if (bufarr->len != 1 && bufarr->len != 2)     /* one header, and count stored in a byte */
1654     goto wrong_count;
1655
1656   /* Opus headers are not in-band */
1657   context->xiph_headers_to_skip = 0;
1658
1659   bufval = &g_array_index (bufarr, GValue, 0);
1660   if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
1661     goto wrong_content_type;
1662   }
1663   buf = g_value_peek_pointer (bufval);
1664
1665   gst_matroska_mux_free_codec_priv (context);
1666
1667   context->codec_priv_size = gst_buffer_get_size (buf);
1668   context->codec_priv = g_malloc0 (context->codec_priv_size);
1669   gst_buffer_extract (buf, 0, context->codec_priv, -1);
1670
1671   context->codec_delay =
1672       GST_READ_UINT16_LE ((guint8 *) context->codec_priv + 10);
1673   context->codec_delay =
1674       gst_util_uint64_scale_round (context->codec_delay, GST_SECOND, 48000);
1675   context->seek_preroll = 80 * GST_MSECOND;
1676
1677   return TRUE;
1678
1679 /* ERRORS */
1680 wrong_type:
1681   {
1682     GST_WARNING ("streamheaders are not a GST_TYPE_ARRAY, but a %s",
1683         G_VALUE_TYPE_NAME (streamheader));
1684     return FALSE;
1685   }
1686 wrong_count:
1687   {
1688     GST_WARNING ("got %u streamheaders, not 1 or 2 as expected", bufarr->len);
1689     return FALSE;
1690   }
1691 wrong_content_type:
1692   {
1693     GST_WARNING ("streamheaders array does not contain GstBuffers");
1694     return FALSE;
1695   }
1696 }
1697
1698 static gboolean
1699 opus_make_codecdata (GstMatroskaTrackContext * context, GstCaps * caps)
1700 {
1701   guint32 rate;
1702   guint8 channels;
1703   guint8 channel_mapping_family;
1704   guint8 stream_count, coupled_count, channel_mapping[256];
1705   GstBuffer *buffer;
1706   GstMapInfo map;
1707
1708   /* Opus headers are not in-band */
1709   context->xiph_headers_to_skip = 0;
1710
1711   context->codec_delay = 0;
1712   context->seek_preroll = 80 * GST_MSECOND;
1713
1714   if (!gst_codec_utils_opus_parse_caps (caps, &rate, &channels,
1715           &channel_mapping_family, &stream_count, &coupled_count,
1716           channel_mapping)) {
1717     GST_WARNING ("Failed to parse caps for Opus");
1718     return FALSE;
1719   }
1720
1721   buffer =
1722       gst_codec_utils_opus_create_header (rate, channels,
1723       channel_mapping_family, stream_count, coupled_count, channel_mapping, 0,
1724       0);
1725   if (!buffer) {
1726     GST_WARNING ("Failed to create Opus header from caps");
1727     return FALSE;
1728   }
1729
1730   gst_buffer_map (buffer, &map, GST_MAP_READ);
1731   context->codec_priv_size = map.size;
1732   context->codec_priv = g_malloc (context->codec_priv_size);
1733   memcpy (context->codec_priv, map.data, map.size);
1734   gst_buffer_unmap (buffer, &map);
1735   gst_buffer_unref (buffer);
1736
1737   return TRUE;
1738 }
1739
1740 /**
1741  * gst_matroska_mux_audio_pad_setcaps:
1742  * @pad: Pad which got the caps.
1743  * @caps: New caps.
1744  *
1745  * Setcaps function for audio sink pad.
1746  *
1747  * Returns: #TRUE on success.
1748  */
1749 static gboolean
1750 gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
1751 {
1752   GstMatroskaTrackContext *context = NULL;
1753   GstMatroskaTrackAudioContext *audiocontext;
1754   GstMatroskaMux *mux;
1755   GstMatroskaPad *collect_pad;
1756   const gchar *mimetype;
1757   gint samplerate = 0, channels = 0;
1758   GstStructure *structure;
1759   const GValue *codec_data = NULL;
1760   GstBuffer *buf = NULL;
1761   const gchar *stream_format = NULL;
1762
1763   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
1764
1765   /* find context */
1766   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
1767   g_assert (collect_pad);
1768   context = collect_pad->track;
1769   g_assert (context);
1770   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO);
1771   audiocontext = (GstMatroskaTrackAudioContext *) context;
1772
1773   structure = gst_caps_get_structure (caps, 0);
1774   mimetype = gst_structure_get_name (structure);
1775
1776   /* general setup */
1777   gst_structure_get_int (structure, "rate", &samplerate);
1778   gst_structure_get_int (structure, "channels", &channels);
1779
1780   audiocontext->samplerate = samplerate;
1781   audiocontext->channels = channels;
1782   audiocontext->bitdepth = 0;
1783   context->default_duration = 0;
1784
1785   codec_data = gst_structure_get_value (structure, "codec_data");
1786   if (codec_data)
1787     buf = gst_value_get_buffer (codec_data);
1788
1789   /* TODO: - check if we handle all codecs by the spec, i.e. codec private
1790    *         data and other settings
1791    *       - add new formats
1792    */
1793
1794   if (!strcmp (mimetype, "audio/mpeg")) {
1795     gint mpegversion = 0;
1796
1797     gst_structure_get_int (structure, "mpegversion", &mpegversion);
1798     switch (mpegversion) {
1799       case 1:{
1800         gint layer;
1801         gint version = 1;
1802         gint spf;
1803
1804         gst_structure_get_int (structure, "layer", &layer);
1805
1806         if (!gst_structure_get_int (structure, "mpegaudioversion", &version)) {
1807           GST_WARNING_OBJECT (mux,
1808               "Unable to determine MPEG audio version, assuming 1");
1809           version = 1;
1810         }
1811
1812         if (layer == 1)
1813           spf = 384;
1814         else if (layer == 2)
1815           spf = 1152;
1816         else if (version == 2)
1817           spf = 576;
1818         else
1819           spf = 1152;
1820
1821         context->default_duration =
1822             gst_util_uint64_scale (GST_SECOND, spf, audiocontext->samplerate);
1823
1824         switch (layer) {
1825           case 1:
1826             gst_matroska_mux_set_codec_id (context,
1827                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1);
1828             break;
1829           case 2:
1830             gst_matroska_mux_set_codec_id (context,
1831                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2);
1832             break;
1833           case 3:
1834             gst_matroska_mux_set_codec_id (context,
1835                 GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3);
1836             break;
1837           default:
1838             goto refuse_caps;
1839         }
1840         break;
1841       }
1842       case 2:
1843       case 4:
1844         stream_format = gst_structure_get_string (structure, "stream-format");
1845         /* check this is raw aac */
1846         if (stream_format) {
1847           if (strcmp (stream_format, "raw") != 0) {
1848             GST_WARNING_OBJECT (mux, "AAC stream-format must be 'raw', not %s",
1849                 stream_format);
1850           }
1851         } else {
1852           GST_WARNING_OBJECT (mux, "AAC stream-format not specified, "
1853               "assuming 'raw'");
1854         }
1855
1856         if (buf) {
1857           context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AAC);
1858           context->codec_priv_size = gst_buffer_get_size (buf);
1859           context->codec_priv = g_malloc (context->codec_priv_size);
1860           gst_buffer_extract (buf, 0, context->codec_priv,
1861               context->codec_priv_size);
1862         } else {
1863           GST_DEBUG_OBJECT (mux, "no AAC codec_data; not packetized");
1864           goto refuse_caps;
1865         }
1866         break;
1867       default:
1868         goto refuse_caps;
1869     }
1870   } else if (!strcmp (mimetype, "audio/x-raw")) {
1871     GstAudioInfo info;
1872
1873     gst_audio_info_init (&info);
1874     if (!gst_audio_info_from_caps (&info, caps)) {
1875       GST_DEBUG_OBJECT (mux,
1876           "broken caps, rejected by gst_audio_info_from_caps");
1877       goto refuse_caps;
1878     }
1879
1880     switch (GST_AUDIO_INFO_FORMAT (&info)) {
1881       case GST_AUDIO_FORMAT_U8:
1882       case GST_AUDIO_FORMAT_S16BE:
1883       case GST_AUDIO_FORMAT_S16LE:
1884       case GST_AUDIO_FORMAT_S24BE:
1885       case GST_AUDIO_FORMAT_S24LE:
1886       case GST_AUDIO_FORMAT_S32BE:
1887       case GST_AUDIO_FORMAT_S32LE:
1888         if (GST_AUDIO_INFO_WIDTH (&info) != GST_AUDIO_INFO_DEPTH (&info)) {
1889           GST_DEBUG_OBJECT (mux, "width must be same as depth!");
1890           goto refuse_caps;
1891         }
1892         if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info))
1893           gst_matroska_mux_set_codec_id (context,
1894               GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
1895         else
1896           gst_matroska_mux_set_codec_id (context,
1897               GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
1898         break;
1899       case GST_AUDIO_FORMAT_F32LE:
1900       case GST_AUDIO_FORMAT_F64LE:
1901         gst_matroska_mux_set_codec_id (context,
1902             GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
1903         break;
1904
1905       default:
1906         GST_DEBUG_OBJECT (mux, "wrong format in raw audio caps");
1907         goto refuse_caps;
1908     }
1909
1910     audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
1911   } else if (!strcmp (mimetype, "audio/x-vorbis")) {
1912     const GValue *streamheader;
1913
1914     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS);
1915
1916     gst_matroska_mux_free_codec_priv (context);
1917
1918     streamheader = gst_structure_get_value (structure, "streamheader");
1919     if (!vorbis_streamheader_to_codecdata (streamheader, context)) {
1920       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1921           ("vorbis stream headers missing or malformed"));
1922       goto refuse_caps;
1923     }
1924   } else if (!strcmp (mimetype, "audio/x-flac")) {
1925     const GValue *streamheader;
1926
1927     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_FLAC);
1928
1929     gst_matroska_mux_free_codec_priv (context);
1930
1931     streamheader = gst_structure_get_value (structure, "streamheader");
1932     if (!flac_streamheader_to_codecdata (streamheader, context)) {
1933       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1934           ("flac stream headers missing or malformed"));
1935       goto refuse_caps;
1936     }
1937   } else if (!strcmp (mimetype, "audio/x-speex")) {
1938     const GValue *streamheader;
1939
1940     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_SPEEX);
1941     gst_matroska_mux_free_codec_priv (context);
1942
1943     streamheader = gst_structure_get_value (structure, "streamheader");
1944     if (!speex_streamheader_to_codecdata (streamheader, context)) {
1945       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1946           ("speex stream headers missing or malformed"));
1947       goto refuse_caps;
1948     }
1949   } else if (!strcmp (mimetype, "audio/x-opus")) {
1950     const GValue *streamheader;
1951
1952     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_OPUS);
1953
1954     streamheader = gst_structure_get_value (structure, "streamheader");
1955     if (streamheader) {
1956       gst_matroska_mux_free_codec_priv (context);
1957       if (!opus_streamheader_to_codecdata (streamheader, context)) {
1958         GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1959             ("opus stream headers missing or malformed"));
1960         goto refuse_caps;
1961       }
1962     } else {
1963       /* no streamheader, but we need to have one, so we make one up
1964          based on caps */
1965       gst_matroska_mux_free_codec_priv (context);
1966       if (!opus_make_codecdata (context, caps)) {
1967         GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
1968             ("opus stream headers missing or malformed"));
1969         goto refuse_caps;
1970       }
1971     }
1972   } else if (!strcmp (mimetype, "audio/x-ac3")) {
1973     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_AC3);
1974   } else if (!strcmp (mimetype, "audio/x-eac3")) {
1975     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_EAC3);
1976   } else if (!strcmp (mimetype, "audio/x-dts")) {
1977     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_DTS);
1978   } else if (!strcmp (mimetype, "audio/x-tta")) {
1979     gint width;
1980
1981     /* TTA frame duration */
1982     context->default_duration = 1.04489795918367346939 * GST_SECOND;
1983
1984     gst_structure_get_int (structure, "width", &width);
1985     audiocontext->bitdepth = width;
1986     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_TTA);
1987
1988   } else if (!strcmp (mimetype, "audio/x-pn-realaudio")) {
1989     gint raversion;
1990     const GValue *mdpr_data;
1991
1992     gst_structure_get_int (structure, "raversion", &raversion);
1993     switch (raversion) {
1994       case 1:
1995         gst_matroska_mux_set_codec_id (context,
1996             GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
1997         break;
1998       case 2:
1999         gst_matroska_mux_set_codec_id (context,
2000             GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
2001         break;
2002       case 8:
2003         gst_matroska_mux_set_codec_id (context,
2004             GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
2005         break;
2006       default:
2007         goto refuse_caps;
2008     }
2009
2010     mdpr_data = gst_structure_get_value (structure, "mdpr_data");
2011     if (mdpr_data != NULL) {
2012       guint8 *priv_data = NULL;
2013       guint priv_data_size = 0;
2014
2015       GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
2016
2017       priv_data_size = gst_buffer_get_size (codec_data_buf);
2018       priv_data = g_malloc0 (priv_data_size);
2019
2020       gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
2021
2022       gst_matroska_mux_free_codec_priv (context);
2023
2024       context->codec_priv = priv_data;
2025       context->codec_priv_size = priv_data_size;
2026     }
2027
2028   } else if (!strcmp (mimetype, "audio/x-wma")
2029       || !strcmp (mimetype, "audio/x-alaw")
2030       || !strcmp (mimetype, "audio/x-mulaw")
2031       || !strcmp (mimetype, "audio/x-adpcm")) {
2032     guint8 *codec_priv;
2033     guint codec_priv_size;
2034     guint16 format = 0;
2035     gint block_align = 0;
2036     gint bitrate = 0;
2037
2038     if (samplerate == 0 || channels == 0) {
2039       GST_WARNING_OBJECT (mux, "Missing channels/samplerate on caps");
2040       goto refuse_caps;
2041     }
2042
2043     if (!strcmp (mimetype, "audio/x-wma")) {
2044       gint wmaversion;
2045       gint depth;
2046
2047       if (!gst_structure_get_int (structure, "wmaversion", &wmaversion)
2048           || !gst_structure_get_int (structure, "block_align", &block_align)
2049           || !gst_structure_get_int (structure, "bitrate", &bitrate)) {
2050         GST_WARNING_OBJECT (mux, "Missing wmaversion/block_align/bitrate"
2051             " on WMA caps");
2052         goto refuse_caps;
2053       }
2054
2055       switch (wmaversion) {
2056         case 1:
2057           format = GST_RIFF_WAVE_FORMAT_WMAV1;
2058           break;
2059         case 2:
2060           format = GST_RIFF_WAVE_FORMAT_WMAV2;
2061           break;
2062         case 3:
2063           format = GST_RIFF_WAVE_FORMAT_WMAV3;
2064           break;
2065         default:
2066           GST_WARNING_OBJECT (mux, "Unexpected WMA version: %d", wmaversion);
2067           goto refuse_caps;
2068       }
2069
2070       if (gst_structure_get_int (structure, "depth", &depth))
2071         audiocontext->bitdepth = depth;
2072     } else if (!strcmp (mimetype, "audio/x-alaw")
2073         || !strcmp (mimetype, "audio/x-mulaw")) {
2074       audiocontext->bitdepth = 8;
2075       if (!strcmp (mimetype, "audio/x-alaw"))
2076         format = GST_RIFF_WAVE_FORMAT_ALAW;
2077       else
2078         format = GST_RIFF_WAVE_FORMAT_MULAW;
2079
2080       block_align = channels;
2081       bitrate = block_align * samplerate;
2082     } else if (!strcmp (mimetype, "audio/x-adpcm")) {
2083       const char *layout;
2084
2085       layout = gst_structure_get_string (structure, "layout");
2086       if (!layout) {
2087         GST_WARNING_OBJECT (mux, "Missing layout on adpcm caps");
2088         goto refuse_caps;
2089       }
2090
2091       if (!gst_structure_get_int (structure, "block_align", &block_align)) {
2092         GST_WARNING_OBJECT (mux, "Missing block_align on adpcm caps");
2093         goto refuse_caps;
2094       }
2095
2096       if (!strcmp (layout, "dvi")) {
2097         format = GST_RIFF_WAVE_FORMAT_DVI_ADPCM;
2098       } else if (!strcmp (layout, "g726")) {
2099         format = GST_RIFF_WAVE_FORMAT_ITU_G726_ADPCM;
2100         if (!gst_structure_get_int (structure, "bitrate", &bitrate)) {
2101           GST_WARNING_OBJECT (mux, "Missing bitrate on adpcm g726 caps");
2102           goto refuse_caps;
2103         }
2104       } else {
2105         GST_WARNING_OBJECT (mux, "Unknown layout on adpcm caps");
2106         goto refuse_caps;
2107       }
2108
2109     }
2110     g_assert (format != 0);
2111
2112     codec_priv_size = WAVEFORMATEX_SIZE;
2113     if (buf)
2114       codec_priv_size += gst_buffer_get_size (buf);
2115
2116     /* serialize waveformatex structure */
2117     codec_priv = g_malloc0 (codec_priv_size);
2118     GST_WRITE_UINT16_LE (codec_priv, format);
2119     GST_WRITE_UINT16_LE (codec_priv + 2, channels);
2120     GST_WRITE_UINT32_LE (codec_priv + 4, samplerate);
2121     GST_WRITE_UINT32_LE (codec_priv + 8, bitrate / 8);
2122     GST_WRITE_UINT16_LE (codec_priv + 12, block_align);
2123     GST_WRITE_UINT16_LE (codec_priv + 14, 0);
2124     if (buf)
2125       GST_WRITE_UINT16_LE (codec_priv + 16, gst_buffer_get_size (buf));
2126     else
2127       GST_WRITE_UINT16_LE (codec_priv + 16, 0);
2128
2129     /* process codec private/initialization data, if any */
2130     if (buf) {
2131       gst_buffer_extract (buf, 0,
2132           (guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
2133     }
2134
2135     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_ACM);
2136     gst_matroska_mux_free_codec_priv (context);
2137     context->codec_priv = (gpointer) codec_priv;
2138     context->codec_priv_size = codec_priv_size;
2139   }
2140
2141   return TRUE;
2142
2143   /* ERRORS */
2144 refuse_caps:
2145   {
2146     GST_WARNING_OBJECT (mux, "pad %s refused caps %" GST_PTR_FORMAT,
2147         GST_PAD_NAME (pad), caps);
2148     return FALSE;
2149   }
2150 }
2151
2152 /* we probably don't have the data at start,
2153  * so have to reserve (a maximum) space to write this at the end.
2154  * bit spacy, but some formats can hold quite some */
2155 #define SUBTITLE_MAX_CODEC_PRIVATE   2048       /* must be > 128 */
2156
2157 /**
2158  * gst_matroska_mux_subtitle_pad_setcaps:
2159  * @pad: Pad which got the caps.
2160  * @caps: New caps.
2161  *
2162  * Setcaps function for subtitle sink pad.
2163  *
2164  * Returns: #TRUE on success.
2165  */
2166 static gboolean
2167 gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
2168 {
2169   /* There is now (at least) one such alement (kateenc), and I'm going
2170      to handle it here and claim it works when it can be piped back
2171      through GStreamer and VLC */
2172
2173   GstMatroskaTrackContext *context = NULL;
2174   GstMatroskaTrackSubtitleContext *scontext;
2175   GstMatroskaMux *mux;
2176   GstMatroskaPad *collect_pad;
2177   const gchar *mimetype;
2178   GstStructure *structure;
2179   const GValue *value = NULL;
2180   GstBuffer *buf = NULL;
2181   gboolean ret = TRUE;
2182
2183   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
2184
2185   /* find context */
2186   collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
2187   g_assert (collect_pad);
2188   context = collect_pad->track;
2189   g_assert (context);
2190   g_assert (context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE);
2191   scontext = (GstMatroskaTrackSubtitleContext *) context;
2192
2193   structure = gst_caps_get_structure (caps, 0);
2194   mimetype = gst_structure_get_name (structure);
2195
2196   /* general setup */
2197   scontext->check_utf8 = 1;
2198   scontext->invalid_utf8 = 0;
2199   context->default_duration = 0;
2200
2201   if (!strcmp (mimetype, "subtitle/x-kate")) {
2202     const GValue *streamheader;
2203
2204     gst_matroska_mux_set_codec_id (context,
2205         GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
2206
2207     gst_matroska_mux_free_codec_priv (context);
2208
2209     streamheader = gst_structure_get_value (structure, "streamheader");
2210     if (!kate_streamheader_to_codecdata (streamheader, context)) {
2211       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
2212           ("kate stream headers missing or malformed"));
2213       ret = FALSE;
2214       goto exit;
2215     }
2216   } else if (!strcmp (mimetype, "text/x-raw")) {
2217     gst_matroska_mux_set_codec_id (context,
2218         GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8);
2219   } else if (!strcmp (mimetype, "application/x-ssa")) {
2220     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_SSA);
2221   } else if (!strcmp (mimetype, "application/x-ass")) {
2222     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_ASS);
2223   } else if (!strcmp (mimetype, "application/x-usf")) {
2224     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_USF);
2225   } else if (!strcmp (mimetype, "subpicture/x-dvd")) {
2226     gst_matroska_mux_set_codec_id (context,
2227         GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB);
2228   } else {
2229     ret = FALSE;
2230     goto exit;
2231   }
2232
2233   /* maybe some private data, e.g. vobsub */
2234   value = gst_structure_get_value (structure, "codec_data");
2235   if (value)
2236     buf = gst_value_get_buffer (value);
2237   if (buf != NULL) {
2238     GstMapInfo map;
2239     guint8 *priv_data = NULL;
2240
2241     gst_buffer_map (buf, &map, GST_MAP_READ);
2242
2243     if (map.size > SUBTITLE_MAX_CODEC_PRIVATE) {
2244       GST_WARNING_OBJECT (mux, "pad %" GST_PTR_FORMAT " subtitle private data"
2245           " exceeded maximum (%d); discarding", pad,
2246           SUBTITLE_MAX_CODEC_PRIVATE);
2247       gst_buffer_unmap (buf, &map);
2248       return TRUE;
2249     }
2250
2251     gst_matroska_mux_free_codec_priv (context);
2252
2253     priv_data = g_malloc0 (map.size);
2254     memcpy (priv_data, map.data, map.size);
2255     context->codec_priv = priv_data;
2256     context->codec_priv_size = map.size;
2257     gst_buffer_unmap (buf, &map);
2258   }
2259
2260   GST_DEBUG_OBJECT (pad, "codec_id %s, codec data size %" G_GSIZE_FORMAT,
2261       GST_STR_NULL (context->codec_id), context->codec_priv_size);
2262
2263 exit:
2264
2265   return ret;
2266 }
2267
2268
2269 /**
2270  * gst_matroska_mux_request_new_pad:
2271  * @element: #GstMatroskaMux.
2272  * @templ: #GstPadTemplate.
2273  * @pad_name: New pad name.
2274  *
2275  * Request pad function for sink templates.
2276  *
2277  * Returns: New #GstPad.
2278  */
2279 static GstPad *
2280 gst_matroska_mux_request_new_pad (GstElement * element,
2281     GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
2282 {
2283   GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
2284   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
2285   GstMatroskaPad *collect_pad;
2286   GstMatroskamuxPad *newpad;
2287   gchar *name = NULL;
2288   const gchar *pad_name = NULL;
2289   GstMatroskaCapsFunc capsfunc = NULL;
2290   GstMatroskaTrackContext *context = NULL;
2291   gint pad_id;
2292   gboolean locked = TRUE;
2293   gchar *id = NULL;
2294
2295   if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
2296     /* don't mix named and unnamed pads, if the pad already exists we fail when
2297      * trying to add it */
2298     if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
2299       pad_name = req_name;
2300     } else {
2301       name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
2302       pad_name = name;
2303     }
2304     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
2305     context = (GstMatroskaTrackContext *)
2306         g_new0 (GstMatroskaTrackAudioContext, 1);
2307     context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
2308     context->name = g_strdup ("Audio");
2309   } else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
2310     /* don't mix named and unnamed pads, if the pad already exists we fail when
2311      * trying to add it */
2312     if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
2313       pad_name = req_name;
2314     } else {
2315       name = g_strdup_printf ("video_%u", mux->num_v_streams++);
2316       pad_name = name;
2317     }
2318     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
2319     context = (GstMatroskaTrackContext *)
2320         g_new0 (GstMatroskaTrackVideoContext, 1);
2321     context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
2322     context->name = g_strdup ("Video");
2323   } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%u")) {
2324     /* don't mix named and unnamed pads, if the pad already exists we fail when
2325      * trying to add it */
2326     if (req_name != NULL && sscanf (req_name, "subtitle_%u", &pad_id) == 1) {
2327       pad_name = req_name;
2328     } else {
2329       name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++);
2330       pad_name = name;
2331     }
2332     capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
2333     context = (GstMatroskaTrackContext *)
2334         g_new0 (GstMatroskaTrackSubtitleContext, 1);
2335     context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
2336     context->name = g_strdup ("Subtitle");
2337     /* setcaps may only provide proper one a lot later */
2338     id = g_strdup ("S_SUB_UNKNOWN");
2339     locked = FALSE;
2340   } else {
2341     GST_WARNING_OBJECT (mux, "This is not our template!");
2342     return NULL;
2343   }
2344
2345   newpad = g_object_new (GST_TYPE_MATROSKAMUX_PAD,
2346       "name", pad_name, "direction", templ->direction, "template", templ, NULL);
2347
2348   gst_matroskamux_pad_init (newpad);
2349   collect_pad = (GstMatroskaPad *)
2350       gst_collect_pads_add_pad (mux->collect, GST_PAD (newpad),
2351       sizeof (GstMatroskamuxPad),
2352       (GstCollectDataDestroyNotify) gst_matroska_pad_free, locked);
2353
2354   collect_pad->mux = mux;
2355   collect_pad->track = context;
2356   gst_matroska_pad_reset (collect_pad, FALSE);
2357   collect_pad->track->codec_id = id;
2358   collect_pad->track->dts_only = FALSE;
2359
2360   collect_pad->capsfunc = capsfunc;
2361   gst_pad_set_active (GST_PAD (newpad), TRUE);
2362   if (!gst_element_add_pad (element, GST_PAD (newpad)))
2363     goto pad_add_failed;
2364
2365   g_free (name);
2366
2367   mux->num_streams++;
2368
2369   GST_DEBUG_OBJECT (newpad, "Added new request pad");
2370
2371   return GST_PAD (newpad);
2372
2373   /* ERROR cases */
2374 pad_add_failed:
2375   {
2376     GST_WARNING_OBJECT (mux, "Adding the new pad '%s' failed", pad_name);
2377     g_free (name);
2378     gst_object_unref (newpad);
2379     return NULL;
2380   }
2381 }
2382
2383 /**
2384  * gst_matroska_mux_release_pad:
2385  * @element: #GstMatroskaMux.
2386  * @pad: Pad to release.
2387  *
2388  * Release a previously requested pad.
2389 */
2390 static void
2391 gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
2392 {
2393   GstMatroskaMux *mux;
2394   GSList *walk;
2395
2396   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
2397
2398   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
2399     GstCollectData *cdata = (GstCollectData *) walk->data;
2400     GstMatroskaPad *collect_pad = (GstMatroskaPad *) cdata;
2401
2402     if (cdata->pad == pad) {
2403       /*
2404        * observed duration, this will remain GST_CLOCK_TIME_NONE
2405        * only if the pad is resetted 
2406        */
2407       GstClockTime collected_duration = GST_CLOCK_TIME_NONE;
2408
2409       if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
2410           GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
2411         collected_duration =
2412             GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
2413       }
2414
2415       if (GST_CLOCK_TIME_IS_VALID (collected_duration)
2416           && mux->duration < collected_duration)
2417         mux->duration = collected_duration;
2418
2419       break;
2420     }
2421   }
2422
2423   gst_collect_pads_remove_pad (mux->collect, pad);
2424   if (gst_element_remove_pad (element, pad))
2425     mux->num_streams--;
2426 }
2427
2428
2429 /**
2430  * gst_matroska_mux_track_header:
2431  * @mux: #GstMatroskaMux
2432  * @context: Tack context.
2433  *
2434  * Write a track header.
2435  */
2436 static void
2437 gst_matroska_mux_track_header (GstMatroskaMux * mux,
2438     GstMatroskaTrackContext * context)
2439 {
2440   GstEbmlWrite *ebml = mux->ebml_write;
2441   guint64 master;
2442
2443   /* TODO: check if everything necessary is written and check default values */
2444
2445   /* track type goes before the type-specific stuff */
2446   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKNUMBER, context->num);
2447   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKTYPE, context->type);
2448
2449   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKUID, context->uid);
2450   if (context->default_duration) {
2451     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKDEFAULTDURATION,
2452         context->default_duration);
2453   }
2454   if (context->language) {
2455     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKLANGUAGE,
2456         context->language);
2457   }
2458
2459   /* FIXME: until we have a nice way of getting the codecname
2460    * out of the caps, I'm not going to enable this. Too much
2461    * (useless, double, boring) work... */
2462   /* TODO: Use value from tags if any */
2463   /*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
2464      context->codec_name); */
2465   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
2466
2467   /* type-specific stuff */
2468   switch (context->type) {
2469     case GST_MATROSKA_TRACK_TYPE_VIDEO:{
2470       GstMatroskaTrackVideoContext *videocontext =
2471           (GstMatroskaTrackVideoContext *) context;
2472
2473       master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKVIDEO);
2474       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELWIDTH,
2475           videocontext->pixel_width);
2476       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELHEIGHT,
2477           videocontext->pixel_height);
2478       if (videocontext->display_width && videocontext->display_height) {
2479         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEODISPLAYWIDTH,
2480             videocontext->display_width);
2481         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEODISPLAYHEIGHT,
2482             videocontext->display_height);
2483       }
2484       if (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED)
2485         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOFLAGINTERLACED, 1);
2486       if (videocontext->fourcc) {
2487         guint32 fcc_le = GUINT32_TO_LE (videocontext->fourcc);
2488
2489         gst_ebml_write_binary (ebml, GST_MATROSKA_ID_VIDEOCOLOURSPACE,
2490             (gpointer) & fcc_le, 4);
2491       }
2492       if (videocontext->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
2493         guint64 stereo_mode = 0;
2494
2495         switch (videocontext->multiview_mode) {
2496           case GST_VIDEO_MULTIVIEW_MODE_MONO:
2497             break;
2498           case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
2499             if (videocontext->multiview_flags &
2500                 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST)
2501               stereo_mode = GST_MATROSKA_STEREO_MODE_SBS_RL;
2502             else
2503               stereo_mode = GST_MATROSKA_STEREO_MODE_SBS_LR;
2504             break;
2505           case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
2506             if (videocontext->multiview_flags &
2507                 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST)
2508               stereo_mode = GST_MATROSKA_STEREO_MODE_TB_RL;
2509             else
2510               stereo_mode = GST_MATROSKA_STEREO_MODE_TB_LR;
2511             break;
2512           case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
2513             if (videocontext->multiview_flags &
2514                 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST)
2515               stereo_mode = GST_MATROSKA_STEREO_MODE_CHECKER_RL;
2516             else
2517               stereo_mode = GST_MATROSKA_STEREO_MODE_CHECKER_LR;
2518             break;
2519           case GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME:
2520             if (videocontext->multiview_flags &
2521                 GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST)
2522               stereo_mode = GST_MATROSKA_STEREO_MODE_FBF_RL;
2523             else
2524               stereo_mode = GST_MATROSKA_STEREO_MODE_FBF_LR;
2525             /* FIXME: In frame-by-frame mode, left/right frame buffers need to be
2526              * laced within one block. See http://www.matroska.org/technical/specs/index.html#StereoMode */
2527             GST_FIXME_OBJECT (mux,
2528                 "Frame-by-frame stereoscopic mode not fully implemented");
2529             break;
2530           default:
2531             GST_WARNING_OBJECT (mux,
2532                 "Multiview mode %d not supported in Matroska/WebM",
2533                 videocontext->multiview_mode);
2534             break;
2535         }
2536
2537         if (stereo_mode != 0)
2538           gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOSTEREOMODE,
2539               stereo_mode);
2540       }
2541       gst_ebml_write_master_finish (ebml, master);
2542
2543       break;
2544     }
2545
2546     case GST_MATROSKA_TRACK_TYPE_AUDIO:{
2547       GstMatroskaTrackAudioContext *audiocontext =
2548           (GstMatroskaTrackAudioContext *) context;
2549
2550       master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKAUDIO);
2551       if (audiocontext->samplerate != 8000)
2552         gst_ebml_write_float (ebml, GST_MATROSKA_ID_AUDIOSAMPLINGFREQ,
2553             audiocontext->samplerate);
2554       if (audiocontext->channels != 1)
2555         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOCHANNELS,
2556             audiocontext->channels);
2557       if (audiocontext->bitdepth) {
2558         gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOBITDEPTH,
2559             audiocontext->bitdepth);
2560       }
2561
2562       gst_ebml_write_master_finish (ebml, master);
2563
2564       break;
2565     }
2566
2567     case GST_MATROSKA_TRACK_TYPE_SUBTITLE:{
2568       break;
2569     }
2570     default:
2571       /* doesn't need type-specific data */
2572       break;
2573   }
2574
2575   gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CODECID, context->codec_id);
2576   if (context->codec_priv)
2577     gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
2578         context->codec_priv, context->codec_priv_size);
2579
2580   if (context->seek_preroll) {
2581     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKPREROLL,
2582         context->seek_preroll);
2583   }
2584
2585   if (context->codec_delay) {
2586     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CODECDELAY,
2587         context->codec_delay);
2588   }
2589 }
2590
2591 #if 0
2592 static void
2593 gst_matroska_mux_write_chapter_title (const gchar * title, GstEbmlWrite * ebml)
2594 {
2595   guint64 title_master;
2596
2597   title_master =
2598       gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CHAPTERDISPLAY);
2599
2600   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CHAPSTRING, title);
2601   gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CHAPLANGUAGE,
2602       GST_MATROSKA_MUX_CHAPLANG);
2603
2604   gst_ebml_write_master_finish (ebml, title_master);
2605 }
2606
2607 static void
2608 gst_matroska_mux_write_chapter (GstMatroskaMux * mux, GstTocEntry * edition,
2609     GstTocEntry * entry, GstEbmlWrite * ebml, guint64 * master_chapters,
2610     guint64 * master_edition)
2611 {
2612   guint64 uid, master_chapteratom;
2613   GList *cur;
2614   GstTocEntry *cur_entry;
2615   guint count, i;
2616   gchar *title;
2617   gint64 start, stop;
2618
2619   if (G_UNLIKELY (master_chapters != NULL && *master_chapters == 0))
2620     *master_chapters =
2621         gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CHAPTERS);
2622
2623   if (G_UNLIKELY (master_edition != NULL && *master_edition == 0)) {
2624     /* create uid for the parent */
2625     uid = gst_matroska_mux_create_uid ();
2626     g_free (edition->uid);
2627     edition->uid = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
2628
2629     *master_edition =
2630         gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_EDITIONENTRY);
2631
2632     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_EDITIONUID, uid);
2633     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_EDITIONFLAGHIDDEN, 0);
2634     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_EDITIONFLAGDEFAULT, 0);
2635     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_EDITIONFLAGORDERED, 0);
2636   }
2637
2638   uid = gst_matroska_mux_create_uid ();
2639   gst_toc_entry_get_start_stop_times (entry, &start, &stop);
2640
2641   master_chapteratom =
2642       gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CHAPTERATOM);
2643   g_free (entry->uid);
2644   entry->uid = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
2645   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CHAPTERUID, uid);
2646   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CHAPTERTIMESTART, start);
2647   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CHAPTERTIMESTOP, stop);
2648   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CHAPTERFLAGHIDDEN, 0);
2649   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CHAPTERFLAGENABLED, 1);
2650
2651   cur = entry->subentries;
2652   while (cur != NULL) {
2653     cur_entry = cur->data;
2654     gst_matroska_mux_write_chapter (mux, NULL, cur_entry, ebml, NULL, NULL);
2655
2656     cur = cur->next;
2657   }
2658
2659   if (G_LIKELY (entry->tags != NULL)) {
2660     count = gst_tag_list_get_tag_size (entry->tags, GST_TAG_TITLE);
2661
2662     for (i = 0; i < count; ++i) {
2663       gst_tag_list_get_string_index (entry->tags, GST_TAG_TITLE, i, &title);
2664       gst_matroska_mux_write_chapter_title (title, ebml);
2665       g_free (title);
2666     }
2667
2668     /* remove title tag */
2669     if (G_LIKELY (count > 0))
2670       gst_tag_list_remove_tag (entry->tags, GST_TAG_TITLE);
2671   }
2672
2673   gst_ebml_write_master_finish (ebml, master_chapteratom);
2674 }
2675
2676 static void
2677 gst_matroska_mux_write_chapter_edition (GstMatroskaMux * mux,
2678     GstTocEntry * entry, GstEbmlWrite * ebml, guint64 * master_chapters)
2679 {
2680   guint64 master_edition = 0;
2681   GList *cur;
2682   GstTocEntry *subentry;
2683
2684   cur = gst_toc_entry_get_sub_entries (entry);
2685   while (cur != NULL) {
2686     subentry = cur->data;
2687     gst_matroska_mux_write_chapter (mux, entry, subentry, ebml, master_chapters,
2688         &master_edition);
2689
2690     cur = cur->next;
2691   }
2692
2693   if (G_LIKELY (master_edition != 0))
2694     gst_ebml_write_master_finish (ebml, master_edition);
2695 }
2696 #endif
2697
2698 /**
2699  * gst_matroska_mux_start:
2700  * @mux: #GstMatroskaMux
2701  *
2702  * Start a new matroska file (write headers etc...)
2703  */
2704 static void
2705 gst_matroska_mux_start (GstMatroskaMux * mux)
2706 {
2707   GstEbmlWrite *ebml = mux->ebml_write;
2708   const gchar *doctype;
2709   guint32 seekhead_id[] = { GST_MATROSKA_ID_SEGMENTINFO,
2710     GST_MATROSKA_ID_TRACKS,
2711     GST_MATROSKA_ID_CHAPTERS,
2712     GST_MATROSKA_ID_CUES,
2713     GST_MATROSKA_ID_TAGS,
2714     0
2715   };
2716   const gchar *media_type;
2717   gboolean audio_only;
2718   guint64 master, child;
2719   GSList *collected;
2720   int i;
2721   guint tracknum = 1;
2722   GstClockTime duration = 0;
2723   guint32 segment_uid[4];
2724   GTimeVal time = { 0, 0 };
2725   gchar s_id[32];
2726 #if 0
2727   GstToc *toc;
2728 #endif
2729
2730   /* if not streaming, check if downstream is seekable */
2731   if (!mux->ebml_write->streamable) {
2732     gboolean seekable;
2733     GstQuery *query;
2734
2735     query = gst_query_new_seeking (GST_FORMAT_BYTES);
2736     if (gst_pad_peer_query (mux->srcpad, query)) {
2737       gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
2738       GST_INFO_OBJECT (mux, "downstream is %sseekable", seekable ? "" : "not ");
2739     } else {
2740       /* assume seeking is not supported if query not handled downstream */
2741       GST_WARNING_OBJECT (mux, "downstream did not handle seeking query");
2742       seekable = FALSE;
2743     }
2744     if (!seekable) {
2745       mux->ebml_write->streamable = TRUE;
2746       g_object_notify (G_OBJECT (mux), "streamable");
2747       GST_WARNING_OBJECT (mux, "downstream is not seekable, but "
2748           "streamable=false. Will ignore that and create streamable output "
2749           "instead");
2750     }
2751     gst_query_unref (query);
2752   }
2753
2754   /* stream-start (FIXME: create id based on input ids) */
2755   g_snprintf (s_id, sizeof (s_id), "matroskamux-%08x", g_random_int ());
2756   gst_pad_push_event (mux->srcpad, gst_event_new_stream_start (s_id));
2757
2758   /* output caps */
2759   audio_only = mux->num_v_streams == 0 && mux->num_a_streams > 0;
2760   if (mux->is_webm) {
2761     media_type = (audio_only) ? "audio/webm" : "video/webm";
2762   } else {
2763     media_type = (audio_only) ? "audio/x-matroska" : "video/x-matroska";
2764   }
2765   ebml->caps = gst_caps_new_empty_simple (media_type);
2766   gst_pad_set_caps (mux->srcpad, ebml->caps);
2767   /* we start with a EBML header */
2768   doctype = mux->doctype;
2769   GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
2770       doctype, mux->doctype_version);
2771   gst_ebml_write_header (ebml, doctype, mux->doctype_version);
2772
2773   /* the rest of the header is cached */
2774   gst_ebml_write_set_cache (ebml, 0x1000);
2775
2776   /* start a segment */
2777   mux->segment_pos =
2778       gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENT);
2779   mux->segment_master = ebml->pos;
2780
2781   if (!mux->ebml_write->streamable) {
2782     /* seekhead (table of contents) - we set the positions later */
2783     mux->seekhead_pos = ebml->pos;
2784     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKHEAD);
2785     for (i = 0; seekhead_id[i] != 0; i++) {
2786       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEEKENTRY);
2787       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKID, seekhead_id[i]);
2788       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKPOSITION, -1);
2789       gst_ebml_write_master_finish (ebml, child);
2790     }
2791     gst_ebml_write_master_finish (ebml, master);
2792   }
2793
2794   if (mux->ebml_write->streamable) {
2795     const GstTagList *tags;
2796     gboolean has_main_tags;
2797
2798     /* tags */
2799     tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
2800     has_main_tags = tags != NULL && !gst_matroska_mux_tag_list_is_empty (tags);
2801
2802     if (has_main_tags || gst_matroska_mux_streams_have_tags (mux)) {
2803       guint64 master_tags, master_tag;
2804
2805       GST_DEBUG_OBJECT (mux, "Writing tags");
2806
2807       mux->tags_pos = ebml->pos;
2808       master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
2809       if (has_main_tags) {
2810         master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
2811         gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
2812         gst_ebml_write_master_finish (ebml, master_tag);
2813       }
2814       gst_matroska_mux_write_streams_tags (mux);
2815       gst_ebml_write_master_finish (ebml, master_tags);
2816     }
2817   }
2818
2819   /* segment info */
2820   mux->info_pos = ebml->pos;
2821   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);
2822
2823   /* WebM does not support SegmentUID field on SegmentInfo */
2824   if (!mux->is_webm) {
2825     for (i = 0; i < 4; i++) {
2826       segment_uid[i] = g_random_int ();
2827     }
2828     gst_ebml_write_binary (ebml, GST_MATROSKA_ID_SEGMENTUID,
2829         (guint8 *) segment_uid, 16);
2830   }
2831
2832   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TIMECODESCALE, mux->time_scale);
2833   mux->duration_pos = ebml->pos;
2834   /* get duration */
2835   if (!mux->ebml_write->streamable) {
2836     for (collected = mux->collect->data; collected;
2837         collected = g_slist_next (collected)) {
2838       GstMatroskaPad *collect_pad;
2839       GstPad *thepad;
2840       gint64 trackduration;
2841
2842       collect_pad = (GstMatroskaPad *) collected->data;
2843       thepad = collect_pad->collect.pad;
2844
2845       /* Query the total length of the track. */
2846       GST_DEBUG_OBJECT (thepad, "querying peer duration");
2847       if (gst_pad_peer_query_duration (thepad, GST_FORMAT_TIME, &trackduration)) {
2848         GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
2849             GST_TIME_ARGS (trackduration));
2850         if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
2851           duration = (GstClockTime) trackduration;
2852         }
2853       }
2854     }
2855     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
2856         gst_guint64_to_gdouble (duration) /
2857         gst_guint64_to_gdouble (mux->time_scale));
2858   }
2859   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_MUXINGAPP,
2860       "GStreamer matroskamux version " PACKAGE_VERSION);
2861   if (mux->writing_app && mux->writing_app[0]) {
2862     gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, mux->writing_app);
2863   }
2864   g_get_current_time (&time);
2865   gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time.tv_sec);
2866   gst_ebml_write_master_finish (ebml, master);
2867
2868   /* tracks */
2869   mux->tracks_pos = ebml->pos;
2870   master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKS);
2871
2872   for (collected = mux->collect->data; collected;
2873       collected = g_slist_next (collected)) {
2874     GstMatroskaPad *collect_pad;
2875     GstPad *thepad;
2876
2877     collect_pad = (GstMatroskaPad *) collected->data;
2878     thepad = collect_pad->collect.pad;
2879
2880     if (gst_pad_is_linked (thepad) && gst_pad_is_active (thepad) &&
2881         collect_pad->track->codec_id != 0) {
2882       collect_pad->track->num = tracknum++;
2883       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
2884       gst_matroska_mux_track_header (mux, collect_pad->track);
2885       gst_ebml_write_master_finish (ebml, child);
2886       /* some remaining pad/track setup */
2887       collect_pad->default_duration_scaled =
2888           gst_util_uint64_scale (collect_pad->track->default_duration,
2889           1, mux->time_scale);
2890     }
2891   }
2892   gst_ebml_write_master_finish (ebml, master);
2893
2894   /* FIXME: Check if we get a TOC that is supported by Matroska
2895    * and clean up the code below */
2896 #if 0
2897   /* chapters */
2898   toc = gst_toc_setter_get_toc (GST_TOC_SETTER (mux));
2899   if (toc != NULL && !mux->ebml_write->streamable) {
2900     guint64 master_chapters = 0;
2901     GstTocEntry *toc_entry;
2902     GList *cur, *to_write = NULL;
2903     gint64 start, stop;
2904
2905     GST_DEBUG ("Writing chapters");
2906
2907     /* check whether we have editions or chapters at the root level */
2908     toc_entry = toc->entries->data;
2909
2910     if (toc_entry->type != GST_TOC_ENTRY_TYPE_EDITION) {
2911       toc_entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, "");
2912       gst_toc_entry_set_start_stop_times (toc_entry, -1, -1);
2913
2914       /* aggregate all chapters without root edition */
2915       cur = gst_toc_get_entries (toc);
2916       while (cur != NULL) {
2917         toc_entry->subentries =
2918             g_list_prepend (toc_entry->subentries, cur->data);
2919         cur = cur->next;
2920       }
2921
2922       gst_toc_entry_get_start_stop_times (((GstTocEntry *)
2923               toc_entry->subentries->data), &start, NULL);
2924       toc_entry->subentries = g_list_reverse (toc_entry->subentries);
2925       gst_toc_entry_get_start_stop_times (((GstTocEntry *)
2926               toc_entry->subentries->data), NULL, &stop);
2927       gst_toc_entry_set_start_stop_times (toc_entry, start, stop);
2928
2929       to_write = g_list_append (to_write, toc_entry);
2930     } else {
2931       toc_entry = NULL;
2932       to_write = toc->entries;
2933     }
2934
2935     /* finally write chapters */
2936     mux->chapters_pos = ebml->pos;
2937
2938     cur = to_write;
2939     while (cur != NULL) {
2940       gst_matroska_mux_write_chapter_edition (mux, cur->data, ebml,
2941           &master_chapters);
2942       cur = cur->next;
2943     }
2944
2945     /* close master element if any edition was written */
2946     if (G_LIKELY (master_chapters != 0))
2947       gst_ebml_write_master_finish (ebml, master_chapters);
2948
2949     if (toc_entry != NULL) {
2950       g_list_free (toc_entry->subentries);
2951       toc_entry->subentries = NULL;
2952       gst_toc_entry_unref (toc_entry);
2953       g_list_free (to_write);
2954     }
2955   }
2956 #endif
2957
2958   /* lastly, flush the cache */
2959   gst_ebml_write_flush_cache (ebml, FALSE, 0);
2960
2961 #if 0
2962   if (toc != NULL)
2963     gst_toc_unref (toc);
2964 #endif
2965 }
2966
2967 /* TODO: more sensible tag mappings */
2968 static const struct
2969 {
2970   const gchar *matroska_tagname;
2971   const gchar *gstreamer_tagname;
2972 }
2973 gst_matroska_tag_conv[] = {
2974   {
2975   GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2976   GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
2977   GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2978   GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2979   GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2980   GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2981   GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2982   GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2983   GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2984   GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2985   GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2986   GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2987   GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2988   GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2989   GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2990 };
2991
2992 /* Every stagefright implementation on android up to and including 6.0.1 is using
2993  libwebm with bug in matroska parsing, where it will choke on empty tag elements;
2994  so before outputting tags and tag elements we better make sure that there are
2995  actually tags we are going to write */
2996 static gboolean
2997 gst_matroska_mux_tag_list_is_empty (const GstTagList * list)
2998 {
2999   int i;
3000   for (i = 0; i < gst_tag_list_n_tags (list); i++) {
3001     const gchar *tag = gst_tag_list_nth_tag_name (list, i);
3002     int i;
3003     for (i = 0; i < G_N_ELEMENTS (gst_matroska_tag_conv); i++) {
3004       const gchar *tagname_gst = gst_matroska_tag_conv[i].gstreamer_tagname;
3005       if (strcmp (tagname_gst, tag) == 0) {
3006         GValue src = { 0, };
3007         gchar *dest;
3008
3009         if (!gst_tag_list_copy_value (&src, list, tag))
3010           break;
3011         dest = gst_value_serialize (&src);
3012
3013         g_value_unset (&src);
3014         if (dest) {
3015           g_free (dest);
3016           return FALSE;
3017         }
3018       }
3019     }
3020   }
3021   return TRUE;
3022 }
3023
3024 static void
3025 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
3026     gpointer data)
3027 {
3028   GstEbmlWrite *ebml = (GstEbmlWrite *) data;
3029   guint i;
3030   guint64 simpletag_master;
3031
3032   for (i = 0; i < G_N_ELEMENTS (gst_matroska_tag_conv); i++) {
3033     const gchar *tagname_gst = gst_matroska_tag_conv[i].gstreamer_tagname;
3034     const gchar *tagname_mkv = gst_matroska_tag_conv[i].matroska_tagname;
3035
3036     if (strcmp (tagname_gst, tag) == 0) {
3037       GValue src = { 0, };
3038       gchar *dest;
3039
3040       if (!gst_tag_list_copy_value (&src, list, tag))
3041         break;
3042       if ((dest = gst_value_serialize (&src))) {
3043
3044         simpletag_master = gst_ebml_write_master_start (ebml,
3045             GST_MATROSKA_ID_SIMPLETAG);
3046         gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_TAGNAME, tagname_mkv);
3047         gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TAGSTRING, dest);
3048         gst_ebml_write_master_finish (ebml, simpletag_master);
3049         g_free (dest);
3050       } else {
3051         GST_WARNING ("Can't transform tag '%s' to string", tagname_mkv);
3052       }
3053       g_value_unset (&src);
3054       break;
3055     }
3056   }
3057 }
3058
3059 static void
3060 gst_matroska_mux_write_stream_tags (GstMatroskaMux * mux, GstMatroskaPad * mpad)
3061 {
3062   guint64 master_tag, master_targets;
3063   GstEbmlWrite *ebml;
3064
3065   ebml = mux->ebml_write;
3066
3067   if (G_UNLIKELY (mpad->tags == NULL
3068           || gst_matroska_mux_tag_list_is_empty (mpad->tags)))
3069     return;
3070
3071   master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
3072   master_targets = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TARGETS);
3073
3074   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TARGETTRACKUID, mpad->track->uid);
3075
3076   gst_ebml_write_master_finish (ebml, master_targets);
3077   gst_tag_list_foreach (mpad->tags, gst_matroska_mux_write_simple_tag, ebml);
3078   gst_ebml_write_master_finish (ebml, master_tag);
3079 }
3080
3081 static void
3082 gst_matroska_mux_write_streams_tags (GstMatroskaMux * mux)
3083 {
3084   GSList *walk;
3085
3086   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
3087     GstMatroskaPad *collect_pad;
3088
3089     collect_pad = (GstMatroskaPad *) walk->data;
3090
3091     gst_matroska_mux_write_stream_tags (mux, collect_pad);
3092   }
3093 }
3094
3095 static gboolean
3096 gst_matroska_mux_streams_have_tags (GstMatroskaMux * mux)
3097 {
3098   GSList *walk;
3099
3100   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
3101     GstMatroskaPad *collect_pad;
3102
3103     collect_pad = (GstMatroskaPad *) walk->data;
3104     if (!gst_matroska_mux_tag_list_is_empty (collect_pad->tags))
3105       return TRUE;
3106   }
3107   return FALSE;
3108 }
3109
3110 #if 0
3111 static void
3112 gst_matroska_mux_write_toc_entry_tags (GstMatroskaMux * mux,
3113     const GstTocEntry * entry, guint64 * master_tags)
3114 {
3115   guint64 master_tag, master_targets;
3116   GstEbmlWrite *ebml;
3117   GList *cur;
3118
3119   ebml = mux->ebml_write;
3120
3121   if (G_UNLIKELY (entry->tags != NULL
3122           && !gst_matroska_mux_tag_list_is_empty (entry->tags))) {
3123     if (*master_tags == 0) {
3124       mux->tags_pos = ebml->pos;
3125       *master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
3126     }
3127
3128     master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
3129     master_targets =
3130         gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TARGETS);
3131
3132     if (entry->type == GST_TOC_ENTRY_TYPE_EDITION)
3133       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TARGETEDITIONUID,
3134           g_ascii_strtoull (entry->uid, NULL, 10));
3135     else
3136       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TARGETCHAPTERUID,
3137           g_ascii_strtoull (entry->uid, NULL, 10));
3138
3139     gst_ebml_write_master_finish (ebml, master_targets);
3140     gst_tag_list_foreach (entry->tags, gst_matroska_mux_write_simple_tag, ebml);
3141     gst_ebml_write_master_finish (ebml, master_tag);
3142   }
3143
3144   cur = entry->subentries;
3145   while (cur != NULL) {
3146     gst_matroska_mux_write_toc_entry_tags (mux, cur->data, master_tags);
3147     cur = cur->next;
3148   }
3149 }
3150 #endif
3151
3152 /**
3153  * gst_matroska_mux_finish:
3154  * @mux: #GstMatroskaMux
3155  *
3156  * Finish a new matroska file (write index etc...)
3157  */
3158 static void
3159 gst_matroska_mux_finish (GstMatroskaMux * mux)
3160 {
3161   GstEbmlWrite *ebml = mux->ebml_write;
3162   guint64 pos;
3163   guint64 duration = 0;
3164   GSList *collected;
3165   const GstTagList *tags;
3166   gboolean has_main_tags;
3167
3168   /* finish last cluster */
3169   if (mux->cluster) {
3170     gst_ebml_write_master_finish (ebml, mux->cluster);
3171   }
3172
3173   /* cues */
3174   if (mux->index != NULL) {
3175     guint n;
3176     guint64 master, pointentry_master, trackpos_master;
3177
3178     mux->cues_pos = ebml->pos;
3179     gst_ebml_write_set_cache (ebml, 12 + 41 * mux->num_indexes);
3180     master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CUES);
3181
3182     for (n = 0; n < mux->num_indexes; n++) {
3183       GstMatroskaIndex *idx = &mux->index[n];
3184
3185       pointentry_master = gst_ebml_write_master_start (ebml,
3186           GST_MATROSKA_ID_POINTENTRY);
3187       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETIME,
3188           idx->time / mux->time_scale);
3189       trackpos_master = gst_ebml_write_master_start (ebml,
3190           GST_MATROSKA_ID_CUETRACKPOSITIONS);
3191       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETRACK, idx->track);
3192       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUECLUSTERPOSITION,
3193           idx->pos - mux->segment_master);
3194       gst_ebml_write_master_finish (ebml, trackpos_master);
3195       gst_ebml_write_master_finish (ebml, pointentry_master);
3196     }
3197
3198     gst_ebml_write_master_finish (ebml, master);
3199     gst_ebml_write_flush_cache (ebml, FALSE, GST_CLOCK_TIME_NONE);
3200   }
3201
3202   /* tags */
3203   tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (mux));
3204   has_main_tags = tags != NULL && !gst_matroska_mux_tag_list_is_empty (tags);
3205
3206   if (has_main_tags || gst_matroska_mux_streams_have_tags (mux)
3207       || gst_toc_setter_get_toc (GST_TOC_SETTER (mux)) != NULL) {
3208     guint64 master_tags = 0, master_tag;
3209 #if 0
3210     const GstToc *toc;
3211 #endif
3212
3213     GST_DEBUG_OBJECT (mux, "Writing tags");
3214
3215 #if 0
3216     toc = gst_toc_setter_get_toc (GST_TOC_SETTER (mux));
3217 #endif
3218
3219     if (has_main_tags) {
3220       /* TODO: maybe limit via the TARGETS id by looking at the source pad */
3221       mux->tags_pos = ebml->pos;
3222       master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
3223       master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
3224
3225       if (tags != NULL)
3226         gst_tag_list_foreach (tags, gst_matroska_mux_write_simple_tag, ebml);
3227 #if 0
3228       if (toc != NULL)
3229         gst_tag_list_foreach (toc->tags, gst_matroska_mux_write_simple_tag,
3230             ebml);
3231 #endif
3232
3233       gst_ebml_write_master_finish (ebml, master_tag);
3234     }
3235 #if 0
3236     if (toc != NULL) {
3237       cur = toc->entries;
3238       while (cur != NULL) {
3239         gst_matroska_mux_write_toc_entry_tags (mux, cur->data, &master_tags);
3240         cur = cur->next;
3241       }
3242     }
3243 #endif
3244
3245     if (master_tags == 0 && gst_matroska_mux_streams_have_tags (mux)) {
3246       mux->tags_pos = ebml->pos;
3247       master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
3248     }
3249     gst_matroska_mux_write_streams_tags (mux);
3250
3251     if (master_tags != 0)
3252       gst_ebml_write_master_finish (ebml, master_tags);
3253   }
3254
3255   /* update seekhead. We know that:
3256    * - a seekhead contains 5 entries.
3257    * - order of entries is as above.
3258    * - a seekhead has a 4-byte header + 8-byte length
3259    * - each entry is 2-byte master, 2-byte ID pointer,
3260    *     2-byte length pointer, all 8/1-byte length, 4-
3261    *     byte ID and 8-byte length pointer, where the
3262    *     length pointer starts at 20.
3263    * - all entries are local to the segment (so pos - segment_master).
3264    * - so each entry is at 12 + 20 + num * 28. */
3265   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
3266       mux->info_pos - mux->segment_master);
3267   gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
3268       mux->tracks_pos - mux->segment_master);
3269   if (gst_toc_setter_get_toc (GST_TOC_SETTER (mux)) != NULL
3270       && mux->chapters_pos > 0) {
3271     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 88,
3272         mux->chapters_pos - mux->segment_master);
3273   } else {
3274     /* void'ify */
3275     guint64 my_pos = ebml->pos;
3276
3277     gst_ebml_write_seek (ebml, mux->seekhead_pos + 68);
3278     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
3279     gst_ebml_write_seek (ebml, my_pos);
3280   }
3281   if (mux->index != NULL) {
3282     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 116,
3283         mux->cues_pos - mux->segment_master);
3284   } else {
3285     /* void'ify */
3286     guint64 my_pos = ebml->pos;
3287
3288     gst_ebml_write_seek (ebml, mux->seekhead_pos + 96);
3289     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
3290     gst_ebml_write_seek (ebml, my_pos);
3291   }
3292
3293   if (tags != NULL) {
3294     gst_ebml_replace_uint (ebml, mux->seekhead_pos + 144,
3295         mux->tags_pos - mux->segment_master);
3296   } else {
3297     /* void'ify */
3298     guint64 my_pos = ebml->pos;
3299
3300     gst_ebml_write_seek (ebml, mux->seekhead_pos + 124);
3301     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 26);
3302     gst_ebml_write_seek (ebml, my_pos);
3303   }
3304
3305   /* loop tracks:
3306    * - first get the overall duration
3307    *   (a released track may have left a duration in here)
3308    * - write some track header data for subtitles
3309    */
3310   duration = mux->duration;
3311   pos = ebml->pos;
3312   for (collected = mux->collect->data; collected;
3313       collected = g_slist_next (collected)) {
3314     GstMatroskaPad *collect_pad;
3315     /*
3316      * observed duration, this will never remain GST_CLOCK_TIME_NONE
3317      * since this means buffer without timestamps that is not possibile
3318      */
3319     GstClockTime collected_duration = GST_CLOCK_TIME_NONE;
3320
3321     collect_pad = (GstMatroskaPad *) collected->data;
3322
3323     GST_DEBUG_OBJECT (mux,
3324         "Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
3325         " end ts %" GST_TIME_FORMAT, collect_pad,
3326         GST_TIME_ARGS (collect_pad->start_ts),
3327         GST_TIME_ARGS (collect_pad->end_ts));
3328
3329     if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
3330         GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
3331       collected_duration =
3332           GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
3333       GST_DEBUG_OBJECT (collect_pad,
3334           "final track duration: %" GST_TIME_FORMAT,
3335           GST_TIME_ARGS (collected_duration));
3336     } else {
3337       GST_WARNING_OBJECT (collect_pad, "unable to get final track duration");
3338     }
3339     if (GST_CLOCK_TIME_IS_VALID (collected_duration) &&
3340         duration < collected_duration)
3341       duration = collected_duration;
3342
3343   }
3344
3345   /* seek back (optional, but do anyway) */
3346   gst_ebml_write_seek (ebml, pos);
3347
3348   /* update duration */
3349   if (duration != 0) {
3350     GST_DEBUG_OBJECT (mux, "final total duration: %" GST_TIME_FORMAT,
3351         GST_TIME_ARGS (duration));
3352     pos = mux->ebml_write->pos;
3353     gst_ebml_write_seek (ebml, mux->duration_pos);
3354     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
3355         gst_guint64_to_gdouble (duration) /
3356         gst_guint64_to_gdouble (mux->time_scale));
3357     gst_ebml_write_seek (ebml, pos);
3358   } else {
3359     /* void'ify */
3360     guint64 my_pos = ebml->pos;
3361
3362     gst_ebml_write_seek (ebml, mux->duration_pos);
3363     gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 8);
3364     gst_ebml_write_seek (ebml, my_pos);
3365   }
3366   GST_DEBUG_OBJECT (mux, "finishing segment");
3367   /* finish segment - this also writes element length */
3368   gst_ebml_write_master_finish (ebml, mux->segment_pos);
3369 }
3370
3371 /**
3372  * gst_matroska_mux_buffer_header:
3373  * @track: Track context.
3374  * @relative_timestamp: relative timestamp of the buffer
3375  * @flags: Buffer flags.
3376  *
3377  * Create a buffer containing buffer header.
3378  *
3379  * Returns: New buffer.
3380  */
3381 static GstBuffer *
3382 gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
3383     gint16 relative_timestamp, int flags)
3384 {
3385   GstBuffer *hdr;
3386   guint8 *data = g_malloc (4);
3387
3388   hdr = gst_buffer_new_wrapped (data, 4);
3389   /* track num - FIXME: what if num >= 0x80 (unlikely)? */
3390   data[0] = track->num | 0x80;
3391   /* time relative to clustertime */
3392   GST_WRITE_UINT16_BE (data + 1, relative_timestamp);
3393
3394   /* flags */
3395   data[3] = flags;
3396
3397   return hdr;
3398 }
3399
3400 #define DIRAC_PARSE_CODE_SEQUENCE_HEADER 0x00
3401 #define DIRAC_PARSE_CODE_END_OF_SEQUENCE 0x10
3402 #define DIRAC_PARSE_CODE_IS_PICTURE(x) ((x & 0x08) != 0)
3403
3404 static GstBuffer *
3405 gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
3406     GstMatroskaPad * collect_pad, GstBuffer * buf)
3407 {
3408   GstMatroskaTrackVideoContext *ctx =
3409       (GstMatroskaTrackVideoContext *) collect_pad->track;
3410   GstMapInfo map;
3411   guint8 *data;
3412   gsize size;
3413   guint8 parse_code;
3414   guint32 next_parse_offset;
3415   GstBuffer *ret = NULL;
3416   gboolean is_muxing_unit = FALSE;
3417
3418   gst_buffer_map (buf, &map, GST_MAP_READ);
3419   data = map.data;
3420   size = map.size;
3421
3422   if (size < 13) {
3423     gst_buffer_unmap (buf, &map);
3424     gst_buffer_unref (buf);
3425     return ret;
3426   }
3427
3428   /* Check if this buffer contains a picture or end-of-sequence packet */
3429   while (size >= 13) {
3430     if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) {
3431       gst_buffer_unmap (buf, &map);
3432       gst_buffer_unref (buf);
3433       return ret;
3434     }
3435
3436     parse_code = GST_READ_UINT8 (data + 4);
3437     if (parse_code == DIRAC_PARSE_CODE_SEQUENCE_HEADER) {
3438       if (ctx->dirac_unit) {
3439         gst_buffer_unref (ctx->dirac_unit);
3440         ctx->dirac_unit = NULL;
3441       }
3442     } else if (DIRAC_PARSE_CODE_IS_PICTURE (parse_code) ||
3443         parse_code == DIRAC_PARSE_CODE_END_OF_SEQUENCE) {
3444       is_muxing_unit = TRUE;
3445       break;
3446     }
3447
3448     next_parse_offset = GST_READ_UINT32_BE (data + 5);
3449
3450     if (G_UNLIKELY (next_parse_offset == 0 || next_parse_offset > size))
3451       break;
3452
3453     data += next_parse_offset;
3454     size -= next_parse_offset;
3455   }
3456
3457   if (ctx->dirac_unit)
3458     ctx->dirac_unit = gst_buffer_append (ctx->dirac_unit, gst_buffer_ref (buf));
3459   else
3460     ctx->dirac_unit = gst_buffer_ref (buf);
3461
3462   gst_buffer_unmap (buf, &map);
3463
3464   if (is_muxing_unit) {
3465     ret = gst_buffer_make_writable (ctx->dirac_unit);
3466     ctx->dirac_unit = NULL;
3467     gst_buffer_copy_into (ret, buf,
3468         GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
3469     gst_buffer_unref (buf);
3470   } else {
3471     gst_buffer_unref (buf);
3472     ret = NULL;
3473   }
3474
3475   return ret;
3476 }
3477
3478 static void
3479 gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
3480 {
3481   GstCaps *caps;
3482   GstStructure *s;
3483   GValue streamheader = { 0 };
3484   GValue bufval = { 0 };
3485   GstBuffer *streamheader_buffer;
3486   GstEbmlWrite *ebml = mux->ebml_write;
3487
3488   streamheader_buffer = gst_ebml_stop_streamheader (ebml);
3489   caps = gst_caps_copy (mux->ebml_write->caps);
3490   s = gst_caps_get_structure (caps, 0);
3491   g_value_init (&streamheader, GST_TYPE_ARRAY);
3492   g_value_init (&bufval, GST_TYPE_BUFFER);
3493   GST_BUFFER_FLAG_SET (streamheader_buffer, GST_BUFFER_FLAG_HEADER);
3494   gst_value_set_buffer (&bufval, streamheader_buffer);
3495   gst_value_array_append_value (&streamheader, &bufval);
3496   g_value_unset (&bufval);
3497   gst_structure_set_value (s, "streamheader", &streamheader);
3498   g_value_unset (&streamheader);
3499   gst_caps_replace (&ebml->caps, caps);
3500   gst_buffer_unref (streamheader_buffer);
3501   gst_pad_set_caps (mux->srcpad, caps);
3502   gst_caps_unref (caps);
3503 }
3504
3505 /**
3506  * gst_matroska_mux_write_data:
3507  * @mux: #GstMatroskaMux
3508  * @collect_pad: #GstMatroskaPad with the data
3509  *
3510  * Write collected data (called from gst_matroska_mux_collected).
3511  *
3512  * Returns: Result of the gst_pad_push issued to write the data.
3513  */
3514 static GstFlowReturn
3515 gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
3516     GstBuffer * buf)
3517 {
3518   GstEbmlWrite *ebml = mux->ebml_write;
3519   GstBuffer *hdr;
3520   guint64 blockgroup;
3521   gboolean write_duration;
3522   gint16 relative_timestamp;
3523   gint64 relative_timestamp64;
3524   guint64 block_duration, duration_diff = 0;
3525   gboolean is_video_keyframe = FALSE;
3526   gboolean is_video_invisible = FALSE;
3527   GstMatroskamuxPad *pad;
3528   gint flags = 0;
3529   GstClockTime buffer_timestamp;
3530   GstAudioClippingMeta *cmeta = NULL;
3531
3532   /* write data */
3533   pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
3534
3535   /* vorbis/theora headers are retrieved from caps and put in CodecPrivate */
3536   if (collect_pad->track->xiph_headers_to_skip > 0) {
3537     GST_LOG_OBJECT (collect_pad->collect.pad, "dropping streamheader buffer");
3538     gst_buffer_unref (buf);
3539     --collect_pad->track->xiph_headers_to_skip;
3540     return GST_FLOW_OK;
3541   }
3542
3543   /* for dirac we have to queue up everything up to a picture unit */
3544   if (collect_pad->track->codec_id != NULL &&
3545       strcmp (collect_pad->track->codec_id,
3546           GST_MATROSKA_CODEC_ID_VIDEO_DIRAC) == 0) {
3547     buf = gst_matroska_mux_handle_dirac_packet (mux, collect_pad, buf);
3548     if (!buf)
3549       return GST_FLOW_OK;
3550   } else if (strcmp (collect_pad->track->codec_id,
3551           GST_MATROSKA_CODEC_ID_VIDEO_PRORES) == 0) {
3552     /* Remove the 'Frame container atom' header' */
3553     buf = gst_buffer_make_writable (buf);
3554     gst_buffer_resize (buf, 8, gst_buffer_get_size (buf) - 8);
3555   }
3556
3557   buffer_timestamp =
3558       gst_matroska_track_get_buffer_timestamp (collect_pad->track, buf);
3559
3560   /* hm, invalid timestamp (due to --to be fixed--- element upstream);
3561    * this would wreak havoc with time stored in matroska file */
3562   /* TODO: maybe calculate a timestamp by using the previous timestamp
3563    * and default duration */
3564   if (!GST_CLOCK_TIME_IS_VALID (buffer_timestamp)) {
3565     GST_WARNING_OBJECT (collect_pad->collect.pad,
3566         "Invalid buffer timestamp; dropping buffer");
3567     gst_buffer_unref (buf);
3568     return GST_FLOW_OK;
3569   }
3570
3571   if (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_OPUS)
3572       && collect_pad->track->codec_delay) {
3573     /* All timestamps should include the codec delay */
3574     if (buffer_timestamp > collect_pad->track->codec_delay) {
3575       buffer_timestamp += collect_pad->track->codec_delay;
3576     } else {
3577       buffer_timestamp = 0;
3578       duration_diff = collect_pad->track->codec_delay - buffer_timestamp;
3579     }
3580   }
3581
3582   /* set the timestamp for outgoing buffers */
3583   ebml->timestamp = buffer_timestamp;
3584
3585   if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
3586     if (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
3587       GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT,
3588           GST_TIME_ARGS (buffer_timestamp));
3589       is_video_keyframe = TRUE;
3590     } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DECODE_ONLY) &&
3591         (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VP8)
3592             || !strcmp (collect_pad->track->codec_id,
3593                 GST_MATROSKA_CODEC_ID_VIDEO_VP9))) {
3594       GST_LOG_OBJECT (mux,
3595           "have VP8 video invisible frame, " "ts=%" GST_TIME_FORMAT,
3596           GST_TIME_ARGS (buffer_timestamp));
3597       is_video_invisible = TRUE;
3598     }
3599   }
3600
3601   if (mux->cluster) {
3602     /* start a new cluster at every keyframe, at every GstForceKeyUnit event,
3603      * or when we may be reaching the limit of the relative timestamp */
3604     if (mux->cluster_time +
3605         mux->max_cluster_duration < buffer_timestamp
3606         || is_video_keyframe || mux->force_key_unit_event) {
3607       if (!mux->ebml_write->streamable)
3608         gst_ebml_write_master_finish (ebml, mux->cluster);
3609
3610       /* Forward the GstForceKeyUnit event after finishing the cluster */
3611       if (mux->force_key_unit_event) {
3612         gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
3613         mux->force_key_unit_event = NULL;
3614       }
3615
3616       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
3617       mux->cluster_pos = ebml->pos;
3618       gst_ebml_write_set_cache (ebml, 0x20);
3619       mux->cluster =
3620           gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
3621       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
3622           gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
3623       GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
3624           gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
3625       gst_ebml_write_flush_cache (ebml, TRUE, buffer_timestamp);
3626       mux->cluster_time = buffer_timestamp;
3627       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
3628           mux->prev_cluster_size);
3629     }
3630   } else {
3631     /* first cluster */
3632
3633     mux->cluster_pos = ebml->pos;
3634     gst_ebml_write_set_cache (ebml, 0x20);
3635     mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
3636     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
3637         gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
3638     gst_ebml_write_flush_cache (ebml, TRUE, buffer_timestamp);
3639     mux->cluster_time = buffer_timestamp;
3640   }
3641
3642   /* We currently write index entries for all video tracks or for the audio
3643    * track in a single-track audio file.  This could be improved by keeping the
3644    * index only for the *first* video track. */
3645
3646   /* TODO: index is useful for every track, should contain the number of
3647    * the block in the cluster which contains the timestamp, should also work
3648    * for files with multiple audio tracks.
3649    */
3650   if (!mux->ebml_write->streamable &&
3651       (is_video_keyframe ||
3652           ((collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO) &&
3653               (mux->num_streams == 1)))) {
3654     gint last_idx = -1;
3655
3656     if (mux->min_index_interval != 0) {
3657       for (last_idx = mux->num_indexes - 1; last_idx >= 0; last_idx--) {
3658         if (mux->index[last_idx].track == collect_pad->track->num)
3659           break;
3660       }
3661     }
3662
3663     if (last_idx < 0 || mux->min_index_interval == 0 ||
3664         (GST_CLOCK_DIFF (mux->index[last_idx].time, buffer_timestamp)
3665             >= mux->min_index_interval)) {
3666       GstMatroskaIndex *idx;
3667
3668       if (mux->num_indexes % 32 == 0) {
3669         mux->index = g_renew (GstMatroskaIndex, mux->index,
3670             mux->num_indexes + 32);
3671       }
3672       idx = &mux->index[mux->num_indexes++];
3673
3674       idx->pos = mux->cluster_pos;
3675       idx->time = buffer_timestamp;
3676       idx->track = collect_pad->track->num;
3677     }
3678   }
3679
3680   /* Check if the duration differs from the default duration. */
3681   write_duration = FALSE;
3682   block_duration = 0;
3683   if (pad->frame_duration && GST_BUFFER_DURATION_IS_VALID (buf)) {
3684     block_duration = GST_BUFFER_DURATION (buf) + duration_diff;
3685     block_duration = gst_util_uint64_scale (block_duration, 1, mux->time_scale);
3686
3687     /* small difference should be ok. */
3688     if (block_duration > collect_pad->default_duration_scaled + 1 ||
3689         block_duration < collect_pad->default_duration_scaled - 1) {
3690       write_duration = TRUE;
3691     }
3692   }
3693
3694   /* write the block, for doctype v2 use SimpleBlock if possible
3695    * one slice (*breath*).
3696    * FIXME: Need to do correct lacing! */
3697   relative_timestamp64 = buffer_timestamp - mux->cluster_time;
3698   if (relative_timestamp64 >= 0) {
3699     /* round the timestamp */
3700     relative_timestamp64 += gst_util_uint64_scale (mux->time_scale, 1, 2);
3701     relative_timestamp = gst_util_uint64_scale (relative_timestamp64, 1,
3702         mux->time_scale);
3703   } else {
3704     /* round the timestamp */
3705     relative_timestamp64 -= gst_util_uint64_scale (mux->time_scale, 1, 2);
3706     relative_timestamp =
3707         -((gint16) gst_util_uint64_scale (-relative_timestamp64, 1,
3708             mux->time_scale));
3709   }
3710
3711   if (is_video_invisible)
3712     flags |= 0x08;
3713
3714   if (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_OPUS)) {
3715     cmeta = gst_buffer_get_audio_clipping_meta (buf);
3716     g_assert (!cmeta || cmeta->format == GST_FORMAT_DEFAULT);
3717
3718     /* Start clipping is done via header and CodecDelay */
3719     if (cmeta && !cmeta->end)
3720       cmeta = NULL;
3721   }
3722
3723   if (mux->doctype_version > 1 && !write_duration && !cmeta) {
3724     if (is_video_keyframe)
3725       flags |= 0x80;
3726
3727     hdr =
3728         gst_matroska_mux_create_buffer_header (collect_pad->track,
3729         relative_timestamp, flags);
3730     gst_ebml_write_set_cache (ebml, 0x40);
3731     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
3732         gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
3733     gst_ebml_write_buffer (ebml, hdr);
3734     gst_ebml_write_flush_cache (ebml, FALSE, buffer_timestamp);
3735     gst_ebml_write_buffer (ebml, buf);
3736
3737     return gst_ebml_last_write_result (ebml);
3738   } else {
3739     gst_ebml_write_set_cache (ebml, gst_buffer_get_size (buf) * 2);
3740     /* write and call order slightly unnatural,
3741      * but avoids seek and minizes pushing */
3742     blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
3743     hdr =
3744         gst_matroska_mux_create_buffer_header (collect_pad->track,
3745         relative_timestamp, flags);
3746     if (write_duration)
3747       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
3748
3749     if (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_OPUS)
3750         && cmeta) {
3751       /* Start clipping is done via header and CodecDelay */
3752       if (cmeta->end) {
3753         guint64 end =
3754             gst_util_uint64_scale_round (cmeta->end, GST_SECOND, 48000);
3755         gst_ebml_write_sint (ebml, GST_MATROSKA_ID_DISCARDPADDING, end);
3756       }
3757     }
3758
3759     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
3760         gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
3761     gst_ebml_write_buffer (ebml, hdr);
3762     gst_ebml_write_master_finish_full (ebml, blockgroup,
3763         gst_buffer_get_size (buf));
3764     gst_ebml_write_flush_cache (ebml, FALSE, buffer_timestamp);
3765     gst_ebml_write_buffer (ebml, buf);
3766
3767     return gst_ebml_last_write_result (ebml);
3768   }
3769 }
3770
3771 /**
3772  * gst_matroska_mux_handle_buffer:
3773  * @pads: #GstCollectPads
3774  * @uuser_data: #GstMatroskaMux
3775  *
3776  * Collectpads callback.
3777  *
3778  * Returns: #GstFlowReturn
3779  */
3780 static GstFlowReturn
3781 gst_matroska_mux_handle_buffer (GstCollectPads * pads, GstCollectData * data,
3782     GstBuffer * buf, gpointer user_data)
3783 {
3784   GstClockTime buffer_timestamp;
3785   GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
3786   GstEbmlWrite *ebml = mux->ebml_write;
3787   GstMatroskaPad *best;
3788   GstFlowReturn ret = GST_FLOW_OK;
3789   GST_DEBUG_OBJECT (mux, "Collected pads");
3790
3791   /* start with a header */
3792   if (mux->state == GST_MATROSKA_MUX_STATE_START) {
3793     if (mux->collect->data == NULL) {
3794       GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
3795           ("No input streams configured"));
3796       return GST_FLOW_ERROR;
3797     }
3798     mux->state = GST_MATROSKA_MUX_STATE_HEADER;
3799     gst_ebml_start_streamheader (ebml);
3800     gst_matroska_mux_start (mux);
3801     gst_matroska_mux_stop_streamheader (mux);
3802     mux->state = GST_MATROSKA_MUX_STATE_DATA;
3803   }
3804
3805   /* provided with stream to write from */
3806   best = (GstMatroskaPad *) data;
3807
3808   /* if there is no best pad, we have reached EOS */
3809   if (best == NULL) {
3810     GST_DEBUG_OBJECT (mux, "No best pad. Finishing...");
3811     if (!mux->ebml_write->streamable) {
3812       gst_matroska_mux_finish (mux);
3813     } else {
3814       GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
3815     }
3816     gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
3817     ret = GST_FLOW_EOS;
3818     goto exit;
3819   }
3820
3821   /* if we have a best stream, should also have a buffer */
3822   g_assert (buf);
3823
3824   buffer_timestamp = gst_matroska_track_get_buffer_timestamp (best->track, buf);
3825
3826   GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
3827       GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
3828       GST_TIME_ARGS (buffer_timestamp),
3829       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
3830
3831   /* make note of first and last encountered timestamps, so we can calculate
3832    * the actual duration later when we send an updated header on eos */
3833   if (GST_CLOCK_TIME_IS_VALID (buffer_timestamp)) {
3834     GstClockTime start_ts = buffer_timestamp;
3835     GstClockTime end_ts = start_ts;
3836
3837     if (GST_BUFFER_DURATION_IS_VALID (buf))
3838       end_ts += GST_BUFFER_DURATION (buf);
3839     else if (best->track->default_duration)
3840       end_ts += best->track->default_duration;
3841
3842     if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
3843       best->end_ts = end_ts;
3844
3845     if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
3846             start_ts < best->start_ts))
3847       best->start_ts = start_ts;
3848   }
3849
3850   /* write one buffer */
3851   ret = gst_matroska_mux_write_data (mux, best, buf);
3852
3853 exit:
3854   return ret;
3855 }
3856
3857
3858 /**
3859  * gst_matroska_mux_change_state:
3860  * @element: #GstMatroskaMux
3861  * @transition: State change transition.
3862  *
3863  * Change the muxer state.
3864  *
3865  * Returns: #GstStateChangeReturn
3866  */
3867 static GstStateChangeReturn
3868 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
3869 {
3870   GstStateChangeReturn ret;
3871   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
3872
3873   switch (transition) {
3874     case GST_STATE_CHANGE_NULL_TO_READY:
3875       break;
3876     case GST_STATE_CHANGE_READY_TO_PAUSED:
3877       gst_collect_pads_start (mux->collect);
3878       break;
3879     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3880       break;
3881     case GST_STATE_CHANGE_PAUSED_TO_READY:
3882       gst_collect_pads_stop (mux->collect);
3883       break;
3884     default:
3885       break;
3886   }
3887
3888   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3889
3890   switch (transition) {
3891     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3892       break;
3893     case GST_STATE_CHANGE_PAUSED_TO_READY:
3894       gst_matroska_mux_reset (GST_ELEMENT (mux));
3895       break;
3896     case GST_STATE_CHANGE_READY_TO_NULL:
3897       break;
3898     default:
3899       break;
3900   }
3901
3902   return ret;
3903 }
3904
3905 static void
3906 gst_matroska_mux_set_property (GObject * object,
3907     guint prop_id, const GValue * value, GParamSpec * pspec)
3908 {
3909   GstMatroskaMux *mux;
3910
3911   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3912   mux = GST_MATROSKA_MUX (object);
3913
3914   switch (prop_id) {
3915     case PROP_WRITING_APP:
3916       if (!g_value_get_string (value)) {
3917         GST_WARNING_OBJECT (mux, "writing-app property can not be NULL");
3918         break;
3919       }
3920       g_free (mux->writing_app);
3921       mux->writing_app = g_value_dup_string (value);
3922       break;
3923     case PROP_DOCTYPE_VERSION:
3924       mux->doctype_version = g_value_get_int (value);
3925       break;
3926     case PROP_MIN_INDEX_INTERVAL:
3927       mux->min_index_interval = g_value_get_int64 (value);
3928       break;
3929     case PROP_STREAMABLE:
3930       mux->ebml_write->streamable = g_value_get_boolean (value);
3931       break;
3932     case PROP_TIMECODESCALE:
3933       mux->time_scale = g_value_get_int64 (value);
3934       break;
3935     default:
3936       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3937       break;
3938   }
3939 }
3940
3941 static void
3942 gst_matroska_mux_get_property (GObject * object,
3943     guint prop_id, GValue * value, GParamSpec * pspec)
3944 {
3945   GstMatroskaMux *mux;
3946
3947   g_return_if_fail (GST_IS_MATROSKA_MUX (object));
3948   mux = GST_MATROSKA_MUX (object);
3949
3950   switch (prop_id) {
3951     case PROP_WRITING_APP:
3952       g_value_set_string (value, mux->writing_app);
3953       break;
3954     case PROP_DOCTYPE_VERSION:
3955       g_value_set_int (value, mux->doctype_version);
3956       break;
3957     case PROP_MIN_INDEX_INTERVAL:
3958       g_value_set_int64 (value, mux->min_index_interval);
3959       break;
3960     case PROP_STREAMABLE:
3961       g_value_set_boolean (value, mux->ebml_write->streamable);
3962       break;
3963     case PROP_TIMECODESCALE:
3964       g_value_set_int64 (value, mux->time_scale);
3965       break;
3966     default:
3967       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3968       break;
3969   }
3970 }