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