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