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