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