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