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