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