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