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