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