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