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