basetsmux: use private copy of g_ptr_array_copy
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / gst / mpegtsmux / gstbasetsmux.c
1 /*
2  * Copyright 2006, 2007, 2008, 2009, 2010 Fluendo S.A.
3  *  Authors: Jan Schmidt <jan@fluendo.com>
4  *           Kapil Agrawal <kapil@fluendo.com>
5  *           Julien Moutte <julien@fluendo.com>
6  *
7  * Copyright (C) 2011 Jan Schmidt <thaytan@noraisin.net>
8  *
9  * This library is licensed under 3 different licenses and you
10  * can choose to use it under the terms of any one of them. The
11  * three licenses are the MPL 1.1, the LGPL and the MIT license.
12  *
13  * MPL:
14  *
15  * The contents of this file are subject to the Mozilla Public License
16  * Version 1.1 (the "License"); you may not use this file except in
17  * compliance with the License. You may obtain a copy of the License at
18  * http://www.mozilla.org/MPL/.
19  *
20  * Software distributed under the License is distributed on an "AS IS"
21  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
22  * License for the specific language governing rights and limitations
23  * under the License.
24  *
25  * LGPL:
26  *
27  * This library is free software; you can redistribute it and/or
28  * modify it under the terms of the GNU Library General Public
29  * License as published by the Free Software Foundation; either
30  * version 2 of the License, or (at your option) any later version.
31  *
32  * This library is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
35  * Library General Public License for more details.
36  *
37  * You should have received a copy of the GNU Library General Public
38  * License along with this library; if not, write to the
39  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
40  * Boston, MA 02110-1301, USA.
41  *
42  * MIT:
43  *
44  * Unless otherwise indicated, Source Code is licensed under MIT license.
45  * See further explanation attached in License Statement (distributed in the file
46  * LICENSE).
47  *
48  * Permission is hereby granted, free of charge, to any person obtaining a copy of
49  * this software and associated documentation files (the "Software"), to deal in
50  * the Software without restriction, including without limitation the rights to
51  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
52  * of the Software, and to permit persons to whom the Software is furnished to do
53  * so, subject to the following conditions:
54  *
55  * The above copyright notice and this permission notice shall be included in all
56  * copies or substantial portions of the Software.
57  *
58  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
64  * SOFTWARE.
65  *
66  * SPDX-License-Identifier: MPL-1.1 OR MIT OR LGPL-2.0-or-later
67  */
68
69 #include <stdio.h>
70 #include <string.h>
71
72 #include <gst/tag/tag.h>
73 #include <gst/video/video.h>
74 #include <gst/mpegts/mpegts.h>
75 #include <gst/pbutils/pbutils.h>
76 #include <gst/videoparsers/gstjpeg2000parse.h>
77 #include <gst/video/video-color.h>
78
79 #include "gstbasetsmux.h"
80 #include "gstbasetsmuxaac.h"
81 #include "gstbasetsmuxttxt.h"
82 #include "gstbasetsmuxopus.h"
83 #include "gstbasetsmuxjpeg2000.h"
84
85 GST_DEBUG_CATEGORY (gst_base_ts_mux_debug);
86 #define GST_CAT_DEFAULT gst_base_ts_mux_debug
87
88 /* GstBaseTsMuxPad */
89
90 G_DEFINE_TYPE (GstBaseTsMuxPad, gst_base_ts_mux_pad, GST_TYPE_AGGREGATOR_PAD);
91
92 /* Internals */
93
94 static void
95 gst_base_ts_mux_pad_reset (GstBaseTsMuxPad * pad)
96 {
97   pad->dts = GST_CLOCK_STIME_NONE;
98   pad->prog_id = -1;
99
100   if (pad->free_func)
101     pad->free_func (pad->prepare_data);
102   pad->prepare_data = NULL;
103   pad->prepare_func = NULL;
104   pad->free_func = NULL;
105
106   if (pad->codec_data)
107     gst_buffer_replace (&pad->codec_data, NULL);
108
109   /* reference owned elsewhere */
110   pad->stream = NULL;
111   pad->prog = NULL;
112
113   if (pad->language) {
114     g_free (pad->language);
115     pad->language = NULL;
116   }
117 }
118
119 /* GstAggregatorPad implementation */
120
121 static GstFlowReturn
122 gst_base_ts_mux_pad_flush (GstAggregatorPad * agg_pad, GstAggregator * agg)
123 {
124   GList *cur;
125   GstBaseTsMux *mux = GST_BASE_TS_MUX (agg);
126
127   /* Send initial segments again after a flush-stop, and also resend the
128    * header sections */
129   mux->first = TRUE;
130
131   /* output PAT, SI tables */
132   tsmux_resend_pat (mux->tsmux);
133   tsmux_resend_si (mux->tsmux);
134
135   /* output PMT for each program */
136   for (cur = mux->tsmux->programs; cur; cur = cur->next) {
137     TsMuxProgram *program = (TsMuxProgram *) cur->data;
138
139     tsmux_resend_pmt (program);
140   }
141
142   return GST_FLOW_OK;
143 }
144
145 /* GObject implementation */
146
147 static void
148 gst_base_ts_mux_pad_dispose (GObject * obj)
149 {
150   GstBaseTsMuxPad *ts_pad = GST_BASE_TS_MUX_PAD (obj);
151
152   gst_base_ts_mux_pad_reset (ts_pad);
153
154   G_OBJECT_CLASS (gst_base_ts_mux_pad_parent_class)->dispose (obj);
155 }
156
157 static void
158 gst_base_ts_mux_pad_class_init (GstBaseTsMuxPadClass * klass)
159 {
160   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
161   GstAggregatorPadClass *gstaggpad_class = GST_AGGREGATOR_PAD_CLASS (klass);
162
163   gobject_class->dispose = gst_base_ts_mux_pad_dispose;
164   gstaggpad_class->flush = gst_base_ts_mux_pad_flush;
165
166   gst_type_mark_as_plugin_api (GST_TYPE_BASE_TS_MUX, 0);
167 }
168
169 static void
170 gst_base_ts_mux_pad_init (GstBaseTsMuxPad * vaggpad)
171 {
172 }
173
174 /* GstBaseTsMux */
175
176 enum
177 {
178   PROP_0,
179   PROP_PROG_MAP,
180   PROP_PAT_INTERVAL,
181   PROP_PMT_INTERVAL,
182   PROP_ALIGNMENT,
183   PROP_SI_INTERVAL,
184   PROP_BITRATE,
185   PROP_PCR_INTERVAL,
186   PROP_SCTE_35_PID,
187   PROP_SCTE_35_NULL_INTERVAL
188 };
189
190 #define DEFAULT_SCTE_35_PID 0
191
192 #define BASETSMUX_DEFAULT_ALIGNMENT    -1
193
194 #define CLOCK_BASE 9LL
195 #define CLOCK_FREQ (CLOCK_BASE * 10000) /* 90 kHz PTS clock */
196 #define CLOCK_FREQ_SCR (CLOCK_FREQ * 300)       /* 27 MHz SCR clock */
197 #define TS_MUX_CLOCK_BASE (TSMUX_CLOCK_FREQ * 10 * 360)
198
199 #define GSTTIME_TO_MPEGTIME(time) \
200     (((time) > 0 ? (gint64) 1 : (gint64) -1) * \
201     (gint64) gst_util_uint64_scale (ABS(time), CLOCK_BASE, GST_MSECOND/10))
202 /* 27 MHz SCR conversions: */
203 #define MPEG_SYS_TIME_TO_GSTTIME(time) (gst_util_uint64_scale ((time), \
204                         GST_USECOND, CLOCK_FREQ_SCR / 1000000))
205 #define GSTTIME_TO_MPEG_SYS_TIME(time) (gst_util_uint64_scale ((time), \
206                         CLOCK_FREQ_SCR / 1000000, GST_USECOND))
207
208 #define DEFAULT_PROG_ID 0
209
210 static GstStaticPadTemplate gst_base_ts_mux_src_factory =
211 GST_STATIC_PAD_TEMPLATE ("src",
212     GST_PAD_SRC,
213     GST_PAD_ALWAYS,
214     GST_STATIC_CAPS ("video/mpegts, "
215         "systemstream = (boolean) true, " "packetsize = (int) { 188, 192} ")
216     );
217
218 typedef struct
219 {
220   GstMapInfo map_info;
221   GstBuffer *buffer;
222 } StreamData;
223
224 G_DEFINE_TYPE_WITH_CODE (GstBaseTsMux, gst_base_ts_mux, GST_TYPE_AGGREGATOR,
225     gst_mpegts_initialize ());
226
227 /* Internals */
228
229 /* Takes over the ref on the buffer */
230 static StreamData *
231 stream_data_new (GstBuffer * buffer)
232 {
233   StreamData *res = g_new (StreamData, 1);
234   res->buffer = buffer;
235   gst_buffer_map (buffer, &(res->map_info), GST_MAP_READ);
236
237   return res;
238 }
239
240 static void
241 stream_data_free (StreamData * data)
242 {
243   if (data) {
244     gst_buffer_unmap (data->buffer, &data->map_info);
245     gst_buffer_unref (data->buffer);
246     g_free (data);
247   }
248 }
249
250 #define parent_class gst_base_ts_mux_parent_class
251
252 static void
253 gst_base_ts_mux_set_header_on_caps (GstBaseTsMux * mux)
254 {
255   GstBuffer *buf;
256   GstStructure *structure;
257   GValue array = { 0 };
258   GValue value = { 0 };
259   GstCaps *caps;
260
261   caps = gst_pad_get_current_caps (GST_AGGREGATOR_SRC_PAD (mux));
262
263   /* If we have no caps, we are possibly shutting down */
264   if (!caps)
265     return;
266
267   caps = gst_caps_make_writable (caps);
268   structure = gst_caps_get_structure (caps, 0);
269
270   g_value_init (&array, GST_TYPE_ARRAY);
271
272   GST_LOG_OBJECT (mux, "setting %u packets into streamheader",
273       g_queue_get_length (&mux->streamheader));
274
275   while ((buf = GST_BUFFER (g_queue_pop_head (&mux->streamheader)))) {
276     g_value_init (&value, GST_TYPE_BUFFER);
277     gst_value_take_buffer (&value, buf);
278     gst_value_array_append_value (&array, &value);
279     g_value_unset (&value);
280   }
281
282   gst_structure_set_value (structure, "streamheader", &array);
283   gst_aggregator_set_src_caps (GST_AGGREGATOR (mux), caps);
284   g_value_unset (&array);
285   gst_caps_unref (caps);
286 }
287
288 static gboolean
289 steal_si_section (GstMpegtsSectionType * type, TsMuxSection * section,
290     TsMux * mux)
291 {
292   g_hash_table_insert (mux->si_sections, type, section);
293
294   return TRUE;
295 }
296
297 static void
298 gst_base_ts_mux_reset (GstBaseTsMux * mux, gboolean alloc)
299 {
300   GstBuffer *buf;
301   GstBaseTsMuxClass *klass = GST_BASE_TS_MUX_GET_CLASS (mux);
302   GHashTable *si_sections = NULL;
303   GList *l;
304
305   mux->first = TRUE;
306   mux->last_flow_ret = GST_FLOW_OK;
307   mux->last_ts = 0;
308   mux->is_delta = TRUE;
309   mux->is_header = FALSE;
310
311   mux->streamheader_sent = FALSE;
312   mux->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
313   gst_event_replace (&mux->force_key_unit_event, NULL);
314
315   if (mux->out_adapter)
316     gst_adapter_clear (mux->out_adapter);
317   mux->output_ts_offset = GST_CLOCK_TIME_NONE;
318
319   if (mux->tsmux) {
320     if (mux->tsmux->si_sections)
321       si_sections = g_hash_table_ref (mux->tsmux->si_sections);
322
323     tsmux_free (mux->tsmux);
324     mux->tsmux = NULL;
325   }
326
327   if (mux->programs) {
328     g_hash_table_destroy (mux->programs);
329   }
330   mux->programs = g_hash_table_new (g_direct_hash, g_direct_equal);
331
332   while ((buf = GST_BUFFER (g_queue_pop_head (&mux->streamheader))))
333     gst_buffer_unref (buf);
334
335   gst_event_replace (&mux->force_key_unit_event, NULL);
336   gst_buffer_replace (&mux->out_buffer, NULL);
337
338   GST_OBJECT_LOCK (mux);
339
340   for (l = GST_ELEMENT (mux)->sinkpads; l; l = l->next) {
341     gst_base_ts_mux_pad_reset (GST_BASE_TS_MUX_PAD (l->data));
342   }
343
344   GST_OBJECT_UNLOCK (mux);
345
346   if (alloc) {
347     g_assert (klass->create_ts_mux);
348
349     mux->tsmux = klass->create_ts_mux (mux);
350
351     /* Preserve user-specified sections across resets */
352     if (si_sections)
353       g_hash_table_foreach_steal (si_sections, (GHRFunc) steal_si_section,
354           mux->tsmux);
355   }
356
357   if (si_sections)
358     g_hash_table_unref (si_sections);
359
360   mux->last_scte35_event_seqnum = GST_SEQNUM_INVALID;
361
362   if (klass->reset)
363     klass->reset (mux);
364 }
365
366 static void
367 release_buffer_cb (guint8 * data, void *user_data)
368 {
369   stream_data_free ((StreamData *) user_data);
370 }
371
372 static GstFlowReturn
373 gst_base_ts_mux_create_stream (GstBaseTsMux * mux, GstBaseTsMuxPad * ts_pad)
374 {
375   GstFlowReturn ret = GST_FLOW_ERROR;
376   GstCaps *caps;
377   GstStructure *s;
378   GstPad *pad;
379   guint st = TSMUX_ST_RESERVED;
380   const gchar *mt;
381   const GValue *value = NULL;
382   GstBuffer *codec_data = NULL;
383   guint8 opus_channel_config_code = 0;
384   guint16 profile = GST_JPEG2000_PARSE_PROFILE_NONE;
385   guint8 main_level = 0;
386   guint32 max_rate = 0;
387   guint8 color_spec = 0;
388   j2k_private_data *private_data = NULL;
389   const gchar *stream_format = NULL;
390
391   pad = GST_PAD (ts_pad);
392   caps = gst_pad_get_current_caps (pad);
393   if (caps == NULL)
394     goto not_negotiated;
395
396   GST_DEBUG_OBJECT (pad, "Creating stream with PID 0x%04x for caps %"
397       GST_PTR_FORMAT, ts_pad->pid, caps);
398
399   s = gst_caps_get_structure (caps, 0);
400
401   mt = gst_structure_get_name (s);
402   value = gst_structure_get_value (s, "codec_data");
403   if (value != NULL)
404     codec_data = gst_value_get_buffer (value);
405
406   stream_format = gst_structure_get_string (s, "stream-format");
407
408   if (strcmp (mt, "video/x-dirac") == 0) {
409     st = TSMUX_ST_VIDEO_DIRAC;
410   } else if (strcmp (mt, "audio/x-ac3") == 0) {
411     st = TSMUX_ST_PS_AUDIO_AC3;
412   } else if (strcmp (mt, "audio/x-dts") == 0) {
413     st = TSMUX_ST_PS_AUDIO_DTS;
414   } else if (strcmp (mt, "audio/x-lpcm") == 0) {
415     st = TSMUX_ST_PS_AUDIO_LPCM;
416   } else if (strcmp (mt, "video/x-h264") == 0) {
417     st = TSMUX_ST_VIDEO_H264;
418   } else if (strcmp (mt, "video/x-h265") == 0) {
419     st = TSMUX_ST_VIDEO_HEVC;
420   } else if (strcmp (mt, "audio/mpeg") == 0) {
421     gint mpegversion;
422
423     if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
424       GST_ERROR_OBJECT (pad, "caps missing mpegversion");
425       goto not_negotiated;
426     }
427
428     switch (mpegversion) {
429       case 1:{
430         int mpegaudioversion = 1;       /* Assume mpegaudioversion=1 for backwards compatibility */
431         (void) gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion);
432
433         if (mpegaudioversion == 1)
434           st = TSMUX_ST_AUDIO_MPEG1;
435         else
436           st = TSMUX_ST_AUDIO_MPEG2;
437         break;
438       }
439       case 2:{
440         /* mpegversion=2 in GStreamer refers to MPEG-2 Part 7 audio,  */
441
442         st = TSMUX_ST_AUDIO_AAC;
443
444         /* Check the stream format. If raw, make dummy internal codec data from the caps */
445         if (g_strcmp0 (stream_format, "raw") == 0) {
446           ts_pad->codec_data =
447               gst_base_ts_mux_aac_mpeg2_make_codec_data (mux, caps);
448           ts_pad->prepare_func = gst_base_ts_mux_prepare_aac_mpeg2;
449           if (ts_pad->codec_data == NULL) {
450             GST_ERROR_OBJECT (mux, "Invalid or incomplete caps for MPEG-2 AAC");
451             goto not_negotiated;
452           }
453         }
454         break;
455       }
456       case 4:
457       {
458         st = TSMUX_ST_AUDIO_AAC;
459
460         /* Check the stream format. We need codec_data with RAW streams and mpegversion=4 */
461         if (g_strcmp0 (stream_format, "raw") == 0) {
462           if (codec_data) {
463             GST_DEBUG_OBJECT (pad,
464                 "we have additional codec data (%" G_GSIZE_FORMAT " bytes)",
465                 gst_buffer_get_size (codec_data));
466             ts_pad->codec_data = gst_buffer_ref (codec_data);
467             ts_pad->prepare_func = gst_base_ts_mux_prepare_aac_mpeg4;
468           } else {
469             ts_pad->codec_data = NULL;
470             GST_ERROR_OBJECT (mux, "Need codec_data for raw MPEG-4 AAC");
471             goto not_negotiated;
472           }
473         }
474         break;
475       }
476       default:
477         GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion);
478         goto not_negotiated;
479     }
480   } else if (strcmp (mt, "video/mpeg") == 0) {
481     gint mpegversion;
482
483     if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
484       GST_ERROR_OBJECT (pad, "caps missing mpegversion");
485       goto not_negotiated;
486     }
487
488     switch (mpegversion) {
489       case 1:
490         st = TSMUX_ST_VIDEO_MPEG1;
491         break;
492       case 2:
493         st = TSMUX_ST_VIDEO_MPEG2;
494         break;
495       case 4:
496         st = TSMUX_ST_VIDEO_MPEG4;
497         break;
498       default:
499         GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion);
500         goto not_negotiated;
501     }
502   } else if (strcmp (mt, "subpicture/x-dvb") == 0) {
503     st = TSMUX_ST_PS_DVB_SUBPICTURE;
504   } else if (strcmp (mt, "application/x-teletext") == 0) {
505     st = TSMUX_ST_PS_TELETEXT;
506     /* needs a particularly sized layout */
507     ts_pad->prepare_func = gst_base_ts_mux_prepare_teletext;
508   } else if (strcmp (mt, "audio/x-opus") == 0) {
509     guint8 channels, mapping_family, stream_count, coupled_count;
510     guint8 channel_mapping[256];
511
512     if (!gst_codec_utils_opus_parse_caps (caps, NULL, &channels,
513             &mapping_family, &stream_count, &coupled_count, channel_mapping)) {
514       GST_ERROR_OBJECT (pad, "Incomplete Opus caps");
515       goto not_negotiated;
516     }
517
518     if (channels <= 2 && mapping_family == 0) {
519       opus_channel_config_code = channels;
520     } else if (channels == 2 && mapping_family == 255 && stream_count == 1
521         && coupled_count == 1) {
522       /* Dual mono */
523       opus_channel_config_code = 0;
524     } else if (channels >= 2 && channels <= 8 && mapping_family == 1) {
525       static const guint8 coupled_stream_counts[9] = {
526         1, 0, 1, 1, 2, 2, 2, 3, 3
527       };
528       static const guint8 channel_map_a[8][8] = {
529         {0},
530         {0, 1},
531         {0, 2, 1},
532         {0, 1, 2, 3},
533         {0, 4, 1, 2, 3},
534         {0, 4, 1, 2, 3, 5},
535         {0, 4, 1, 2, 3, 5, 6},
536         {0, 6, 1, 2, 3, 4, 5, 7},
537       };
538       static const guint8 channel_map_b[8][8] = {
539         {0},
540         {0, 1},
541         {0, 1, 2},
542         {0, 1, 2, 3},
543         {0, 1, 2, 3, 4},
544         {0, 1, 2, 3, 4, 5},
545         {0, 1, 2, 3, 4, 5, 6},
546         {0, 1, 2, 3, 4, 5, 6, 7},
547       };
548
549       /* Vorbis mapping */
550       if (stream_count == channels - coupled_stream_counts[channels] &&
551           coupled_count == coupled_stream_counts[channels] &&
552           memcmp (channel_mapping, channel_map_a[channels - 1],
553               channels) == 0) {
554         opus_channel_config_code = channels;
555       } else if (stream_count == channels - coupled_stream_counts[channels] &&
556           coupled_count == coupled_stream_counts[channels] &&
557           memcmp (channel_mapping, channel_map_b[channels - 1],
558               channels) == 0) {
559         opus_channel_config_code = channels | 0x80;
560       } else {
561         GST_FIXME_OBJECT (pad, "Opus channel mapping not handled");
562         goto not_negotiated;
563       }
564     }
565
566     st = TSMUX_ST_PS_OPUS;
567     ts_pad->prepare_func = gst_base_ts_mux_prepare_opus;
568   } else if (strcmp (mt, "meta/x-klv") == 0) {
569     st = TSMUX_ST_PS_KLV;
570   } else if (strcmp (mt, "image/x-jpc") == 0) {
571     /*
572      * See this document for more details on standard:
573      *
574      * https://www.itu.int/rec/T-REC-H.222.0-201206-S/en
575      *  Annex S describes J2K details
576      *  Page 104 of this document describes J2k video descriptor
577      */
578
579     const GValue *vProfile = gst_structure_get_value (s, "profile");
580     const GValue *vMainlevel = gst_structure_get_value (s, "main-level");
581     const GValue *vFramerate = gst_structure_get_value (s, "framerate");
582     const GValue *vColorimetry = gst_structure_get_value (s, "colorimetry");
583     private_data = g_new0 (j2k_private_data, 1);
584     /* for now, we relax the condition that profile must exist and equal
585      * GST_JPEG2000_PARSE_PROFILE_BC_SINGLE */
586     if (vProfile) {
587       profile = g_value_get_int (vProfile);
588       if (profile != GST_JPEG2000_PARSE_PROFILE_BC_SINGLE) {
589         GST_LOG_OBJECT (pad, "Invalid JPEG 2000 profile %d", profile);
590         /*goto not_negotiated; */
591       }
592     }
593     /* for now, we will relax the condition that the main level must be present */
594     if (vMainlevel) {
595       main_level = g_value_get_uint (vMainlevel);
596       if (main_level > 11) {
597         GST_ERROR_OBJECT (pad, "Invalid main level %d", main_level);
598         goto not_negotiated;
599       }
600       if (main_level >= 6) {
601         max_rate = 2 ^ (main_level - 6) * 1600 * 1000000;
602       } else {
603         switch (main_level) {
604           case 0:
605           case 1:
606           case 2:
607           case 3:
608             max_rate = 200 * 1000000;
609             break;
610           case 4:
611             max_rate = 400 * 1000000;
612             break;
613           case 5:
614             max_rate = 800 * 1000000;
615             break;
616           default:
617             break;
618         }
619       }
620     } else {
621       /*GST_ERROR_OBJECT (pad, "Missing main level");
622          goto not_negotiated; */
623     }
624     /* We always mux video in J2K-over-MPEG-TS non-interlaced mode */
625     private_data->interlace = FALSE;
626     private_data->den = 0;
627     private_data->num = 0;
628     private_data->max_bitrate = max_rate;
629     private_data->color_spec = 1;
630     /* these two fields are not used, since we always mux as non-interlaced */
631     private_data->Fic = 1;
632     private_data->Fio = 0;
633
634     /* Get Framerate */
635     if (vFramerate != NULL) {
636       /* Data for ELSM header */
637       private_data->num = gst_value_get_fraction_numerator (vFramerate);
638       private_data->den = gst_value_get_fraction_denominator (vFramerate);
639     }
640     /* Get Colorimetry */
641     if (vColorimetry) {
642       const char *colorimetry = g_value_get_string (vColorimetry);
643       color_spec = GST_MPEGTS_JPEG2000_COLORSPEC_SRGB;  /* RGB as default */
644       if (g_str_equal (colorimetry, GST_VIDEO_COLORIMETRY_BT601)) {
645         color_spec = GST_MPEGTS_JPEG2000_COLORSPEC_REC601;
646       } else {
647         if (g_str_equal (colorimetry, GST_VIDEO_COLORIMETRY_BT709)
648             || g_str_equal (colorimetry, GST_VIDEO_COLORIMETRY_SMPTE240M)) {
649           color_spec = GST_MPEGTS_JPEG2000_COLORSPEC_REC709;
650         }
651       }
652       private_data->color_spec = color_spec;
653     } else {
654       GST_ERROR_OBJECT (pad, "Colorimetry not present in caps");
655       goto not_negotiated;
656     }
657     st = TSMUX_ST_VIDEO_JP2K;
658     ts_pad->prepare_func = gst_base_ts_mux_prepare_jpeg2000;
659     ts_pad->prepare_data = private_data;
660     ts_pad->free_func = gst_base_ts_mux_free_jpeg2000;
661   } else {
662     GstBaseTsMuxClass *klass = GST_BASE_TS_MUX_GET_CLASS (mux);
663
664     if (klass->handle_media_type) {
665       st = klass->handle_media_type (mux, mt, ts_pad);
666     }
667   }
668
669
670   if (st != TSMUX_ST_RESERVED) {
671     ts_pad->stream = tsmux_create_stream (mux->tsmux, st, ts_pad->pid,
672         ts_pad->language);
673   } else {
674     GST_DEBUG_OBJECT (pad, "Failed to determine stream type");
675   }
676
677   if (ts_pad->stream != NULL) {
678     const char *interlace_mode = gst_structure_get_string (s, "interlace-mode");
679     gst_structure_get_int (s, "rate", &ts_pad->stream->audio_sampling);
680     gst_structure_get_int (s, "channels", &ts_pad->stream->audio_channels);
681     gst_structure_get_int (s, "bitrate", &ts_pad->stream->audio_bitrate);
682
683     /* frame rate */
684     gst_structure_get_fraction (s, "framerate", &ts_pad->stream->num,
685         &ts_pad->stream->den);
686
687     /* Interlace mode */
688     ts_pad->stream->interlace_mode = FALSE;
689     if (interlace_mode) {
690       ts_pad->stream->interlace_mode =
691           g_str_equal (interlace_mode, "interleaved");
692     }
693     /* Width and Height */
694     gst_structure_get_int (s, "width", &ts_pad->stream->horizontal_size);
695     gst_structure_get_int (s, "height", &ts_pad->stream->vertical_size);
696
697     ts_pad->stream->color_spec = color_spec;
698     ts_pad->stream->max_bitrate = max_rate;
699     ts_pad->stream->profile_and_level = profile | main_level;
700
701     ts_pad->stream->opus_channel_config_code = opus_channel_config_code;
702
703     tsmux_stream_set_buffer_release_func (ts_pad->stream, release_buffer_cb);
704     tsmux_program_add_stream (ts_pad->prog, ts_pad->stream);
705
706     ret = GST_FLOW_OK;
707   }
708   gst_caps_unref (caps);
709   return ret;
710   /* ERRORS */
711 not_negotiated:
712   {
713     g_free (private_data);
714     GST_DEBUG_OBJECT (pad, "Sink pad caps were not set before pushing");
715     if (caps)
716       gst_caps_unref (caps);
717     return GST_FLOW_NOT_NEGOTIATED;
718   }
719 }
720
721 static gboolean
722 is_valid_pmt_pid (guint16 pmt_pid)
723 {
724   if (pmt_pid < 0x0010 || pmt_pid > 0x1ffe)
725     return FALSE;
726   return TRUE;
727 }
728
729 static GstFlowReturn
730 gst_base_ts_mux_create_pad_stream (GstBaseTsMux * mux, GstPad * pad)
731 {
732   GstBaseTsMuxPad *ts_pad = GST_BASE_TS_MUX_PAD (pad);
733   gchar *name = NULL;
734   gchar *prop_name;
735   GstFlowReturn ret = GST_FLOW_OK;
736
737   if (ts_pad->prog_id == -1) {
738     name = GST_PAD_NAME (pad);
739     if (mux->prog_map != NULL && gst_structure_has_field (mux->prog_map, name)) {
740       gint idx;
741       gboolean ret = gst_structure_get_int (mux->prog_map, name, &idx);
742       if (!ret) {
743         GST_ELEMENT_ERROR (mux, STREAM, MUX,
744             ("Reading program map failed. Assuming default"), (NULL));
745         idx = DEFAULT_PROG_ID;
746       }
747       if (idx < 0) {
748         GST_DEBUG_OBJECT (mux, "Program number %d associate with pad %s less "
749             "than zero; DEFAULT_PROGRAM = %d is used instead",
750             idx, name, DEFAULT_PROG_ID);
751         idx = DEFAULT_PROG_ID;
752       }
753       ts_pad->prog_id = idx;
754     } else {
755       ts_pad->prog_id = DEFAULT_PROG_ID;
756     }
757   }
758
759   ts_pad->prog =
760       (TsMuxProgram *) g_hash_table_lookup (mux->programs,
761       GINT_TO_POINTER (ts_pad->prog_id));
762   if (ts_pad->prog == NULL) {
763     ts_pad->prog = tsmux_program_new (mux->tsmux, ts_pad->prog_id);
764     if (ts_pad->prog == NULL)
765       goto no_program;
766     tsmux_set_pmt_interval (ts_pad->prog, mux->pmt_interval);
767     tsmux_program_set_scte35_pid (ts_pad->prog, mux->scte35_pid);
768     tsmux_program_set_scte35_interval (ts_pad->prog, mux->scte35_null_interval);
769     g_hash_table_insert (mux->programs, GINT_TO_POINTER (ts_pad->prog_id),
770         ts_pad->prog);
771
772     /* Check for user-specified PMT PID */
773     prop_name = g_strdup_printf ("PMT_%d", ts_pad->prog->pgm_number);
774     if (mux->prog_map && gst_structure_has_field (mux->prog_map, prop_name)) {
775       guint pmt_pid;
776
777       if (gst_structure_get_uint (mux->prog_map, prop_name, &pmt_pid)) {
778         if (is_valid_pmt_pid (pmt_pid)) {
779           GST_DEBUG_OBJECT (mux, "User specified pid=%u as PMT for "
780               "program (prog_id = %d)", pmt_pid, ts_pad->prog->pgm_number);
781           tsmux_program_set_pmt_pid (ts_pad->prog, pmt_pid);
782         } else {
783           GST_ELEMENT_WARNING (mux, LIBRARY, SETTINGS,
784               ("User specified PMT pid %u for program %d is not valid.",
785                   pmt_pid, ts_pad->prog->pgm_number), (NULL));
786         }
787       }
788     }
789     g_free (prop_name);
790   }
791
792   if (ts_pad->stream == NULL) {
793     ret = gst_base_ts_mux_create_stream (mux, ts_pad);
794     if (ret != GST_FLOW_OK)
795       goto no_stream;
796   }
797
798   if (ts_pad->prog->pcr_stream == NULL) {
799     /* Take the first stream of the program for the PCR */
800     GST_DEBUG_OBJECT (ts_pad,
801         "Use stream (pid=%d) from pad as PCR for program (prog_id = %d)",
802         ts_pad->pid, ts_pad->prog_id);
803
804     tsmux_program_set_pcr_stream (ts_pad->prog, ts_pad->stream);
805   }
806
807   /* Check for user-specified PCR PID */
808   prop_name = g_strdup_printf ("PCR_%d", ts_pad->prog->pgm_number);
809   if (mux->prog_map && gst_structure_has_field (mux->prog_map, prop_name)) {
810     const gchar *sink_name =
811         gst_structure_get_string (mux->prog_map, prop_name);
812
813     if (!g_strcmp0 (name, sink_name)) {
814       GST_DEBUG_OBJECT (mux, "User specified stream (pid=%d) as PCR for "
815           "program (prog_id = %d)", ts_pad->pid, ts_pad->prog->pgm_number);
816       tsmux_program_set_pcr_stream (ts_pad->prog, ts_pad->stream);
817     }
818   }
819   g_free (prop_name);
820
821   return ret;
822
823   /* ERRORS */
824 no_program:
825   {
826     GST_ELEMENT_ERROR (mux, STREAM, MUX,
827         ("Could not create new program"), (NULL));
828     return GST_FLOW_ERROR;
829   }
830 no_stream:
831   {
832     GST_ELEMENT_ERROR (mux, STREAM, MUX,
833         ("Could not create handler for stream"), (NULL));
834     return ret;
835   }
836 }
837
838 static gboolean
839 gst_base_ts_mux_create_pad_stream_func (GstElement * element, GstPad * pad,
840     gpointer user_data)
841 {
842   GstFlowReturn *ret = user_data;
843
844   *ret = gst_base_ts_mux_create_pad_stream (GST_BASE_TS_MUX (element), pad);
845
846   return *ret == GST_FLOW_OK;
847 }
848
849 static GstFlowReturn
850 gst_base_ts_mux_create_streams (GstBaseTsMux * mux)
851 {
852   GstFlowReturn ret = GST_FLOW_OK;
853
854   gst_element_foreach_sink_pad (GST_ELEMENT_CAST (mux),
855       gst_base_ts_mux_create_pad_stream_func, &ret);
856
857   return ret;
858 }
859
860 static void
861 new_packet_common_init (GstBaseTsMux * mux, GstBuffer * buf, guint8 * data,
862     guint len)
863 {
864   /* Packets should be at least 188 bytes, but check anyway */
865   g_assert (len >= 2 || !data);
866
867   if (!mux->streamheader_sent && data) {
868     guint pid = ((data[1] & 0x1f) << 8) | data[2];
869     /* if it's a PAT or a PMT */
870     if (pid == 0x00 || (pid >= TSMUX_START_PMT_PID && pid < TSMUX_START_ES_PID)) {
871       GstBuffer *hbuf;
872
873       if (!buf) {
874         hbuf = gst_buffer_new_and_alloc (len);
875         gst_buffer_fill (hbuf, 0, data, len);
876       } else {
877         hbuf = gst_buffer_copy (buf);
878       }
879       GST_LOG_OBJECT (mux,
880           "Collecting packet with pid 0x%04x into streamheaders", pid);
881
882       g_queue_push_tail (&mux->streamheader, hbuf);
883     } else if (!g_queue_is_empty (&mux->streamheader)) {
884       gst_base_ts_mux_set_header_on_caps (mux);
885       mux->streamheader_sent = TRUE;
886     }
887   }
888
889   if (buf) {
890     if (mux->is_header) {
891       GST_LOG_OBJECT (mux, "marking as header buffer");
892       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
893     }
894     if (mux->is_delta) {
895       GST_LOG_OBJECT (mux, "marking as delta unit");
896       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
897     } else {
898       GST_DEBUG_OBJECT (mux, "marking as non-delta unit");
899       mux->is_delta = TRUE;
900     }
901   }
902 }
903
904 static GstFlowReturn
905 gst_base_ts_mux_push_packets (GstBaseTsMux * mux, gboolean force)
906 {
907   GstBufferList *buffer_list;
908   gint align = mux->alignment;
909   gint av, packet_size;
910
911   packet_size = mux->packet_size;
912
913   if (align < 0)
914     align = mux->automatic_alignment;
915
916   av = gst_adapter_available (mux->out_adapter);
917   GST_LOG_OBJECT (mux, "align %d, av %d", align, av);
918
919   if (av == 0)
920     return GST_FLOW_OK;
921
922   /* no alignment, just push all available data */
923   if (align == 0) {
924     buffer_list = gst_adapter_take_buffer_list (mux->out_adapter, av);
925     return gst_aggregator_finish_buffer_list (GST_AGGREGATOR (mux),
926         buffer_list);
927   }
928
929   align *= packet_size;
930
931   if (!force && align > av)
932     return GST_FLOW_OK;
933
934   buffer_list = gst_buffer_list_new_sized ((av / align) + 1);
935
936   GST_LOG_OBJECT (mux, "aligning to %d bytes", align);
937   while (align <= av) {
938     GstBuffer *buf;
939     GstClockTime pts;
940
941     pts = gst_adapter_prev_pts (mux->out_adapter, NULL);
942     buf = gst_adapter_take_buffer (mux->out_adapter, align);
943
944     GST_BUFFER_PTS (buf) = pts;
945
946     gst_buffer_list_add (buffer_list, buf);
947     av -= align;
948   }
949
950   if (av > 0 && force) {
951     GstBuffer *buf;
952     GstClockTime pts;
953     guint8 *data;
954     guint32 header;
955     gint dummy;
956     GstMapInfo map;
957
958     GST_LOG_OBJECT (mux, "handling %d leftover bytes", av);
959
960     pts = gst_adapter_prev_pts (mux->out_adapter, NULL);
961     buf = gst_buffer_new_and_alloc (align);
962
963     GST_BUFFER_PTS (buf) = pts;
964
965     gst_buffer_map (buf, &map, GST_MAP_READ);
966     data = map.data;
967
968     gst_adapter_copy (mux->out_adapter, data, 0, av);
969     gst_adapter_clear (mux->out_adapter);
970
971     data += av;
972     header = GST_READ_UINT32_BE (data - packet_size);
973
974     dummy = (map.size - av) / packet_size;
975     GST_LOG_OBJECT (mux, "adding %d null packets", dummy);
976
977     for (; dummy > 0; dummy--) {
978       gint offset;
979
980       if (packet_size > GST_BASE_TS_MUX_NORMAL_PACKET_LENGTH) {
981         GST_WRITE_UINT32_BE (data, header);
982         /* simply increase header a bit and never mind too much */
983         header++;
984         offset = 4;
985       } else {
986         offset = 0;
987       }
988       GST_WRITE_UINT8 (data + offset, TSMUX_SYNC_BYTE);
989       /* null packet PID */
990       GST_WRITE_UINT16_BE (data + offset + 1, 0x1FFF);
991       /* no adaptation field exists | continuity counter undefined */
992       GST_WRITE_UINT8 (data + offset + 3, 0x10);
993       /* payload */
994       memset (data + offset + 4, 0, GST_BASE_TS_MUX_NORMAL_PACKET_LENGTH - 4);
995       data += packet_size;
996     }
997
998     gst_buffer_unmap (buf, &map);
999     gst_buffer_list_add (buffer_list, buf);
1000   }
1001
1002   return gst_aggregator_finish_buffer_list (GST_AGGREGATOR (mux), buffer_list);
1003 }
1004
1005 static GstFlowReturn
1006 gst_base_ts_mux_collect_packet (GstBaseTsMux * mux, GstBuffer * buf)
1007 {
1008   GST_LOG_OBJECT (mux, "collecting packet size %" G_GSIZE_FORMAT,
1009       gst_buffer_get_size (buf));
1010   gst_adapter_push (mux->out_adapter, buf);
1011
1012   return GST_FLOW_OK;
1013 }
1014
1015 static GstEvent *
1016 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
1017     GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
1018 {
1019   GstClockTime running_time, stream_time;
1020   gboolean all_headers;
1021   guint count;
1022   GstEvent *event = NULL;
1023
1024   g_assert (segment != NULL);
1025
1026   if (pending_event == NULL)
1027     goto out;
1028
1029   if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
1030       timestamp == GST_CLOCK_TIME_NONE)
1031     goto out;
1032
1033   running_time = timestamp;
1034
1035   GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
1036       GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
1037   if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
1038       running_time < pending_key_unit_ts)
1039     goto out;
1040
1041   if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
1042     GST_INFO ("pending force key unit, waiting for keyframe");
1043     goto out;
1044   }
1045
1046   stream_time = gst_segment_to_stream_time (segment,
1047       GST_FORMAT_TIME, timestamp);
1048
1049   if (GST_EVENT_TYPE (pending_event) == GST_EVENT_CUSTOM_DOWNSTREAM) {
1050     gst_video_event_parse_downstream_force_key_unit (pending_event,
1051         NULL, NULL, NULL, &all_headers, &count);
1052   } else {
1053     gst_video_event_parse_upstream_force_key_unit (pending_event, NULL,
1054         &all_headers, &count);
1055   }
1056
1057   event =
1058       gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
1059       running_time, all_headers, count);
1060   gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
1061
1062 out:
1063   return event;
1064 }
1065
1066 /* Called when the TsMux has prepared a packet for output. Return FALSE
1067  * on error */
1068 static gboolean
1069 new_packet_cb (GstBuffer * buf, void *user_data, gint64 new_pcr)
1070 {
1071   GstBaseTsMux *mux = (GstBaseTsMux *) user_data;
1072   GstAggregator *agg = GST_AGGREGATOR (mux);
1073   GstBaseTsMuxClass *klass = GST_BASE_TS_MUX_GET_CLASS (mux);
1074   GstMapInfo map;
1075   GstSegment *agg_segment = &GST_AGGREGATOR_PAD (agg->srcpad)->segment;
1076
1077   g_assert (klass->output_packet);
1078
1079   gst_buffer_map (buf, &map, GST_MAP_READWRITE);
1080
1081   if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buf))) {
1082     /* tsmux isn't generating timestamps. Use the input times */
1083     GST_BUFFER_PTS (buf) = mux->last_ts;
1084   }
1085
1086   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buf))) {
1087     if (!GST_CLOCK_TIME_IS_VALID (mux->output_ts_offset)) {
1088       GstClockTime output_start_time = agg_segment->position;
1089       if (agg_segment->position == -1
1090           || agg_segment->position < agg_segment->start) {
1091         output_start_time = agg_segment->start;
1092       }
1093
1094       mux->output_ts_offset =
1095           GST_CLOCK_DIFF (GST_BUFFER_PTS (buf), output_start_time);
1096
1097       GST_DEBUG_OBJECT (mux, "New output ts offset %" GST_STIME_FORMAT,
1098           GST_STIME_ARGS (mux->output_ts_offset));
1099     }
1100
1101     if (GST_CLOCK_TIME_IS_VALID (mux->output_ts_offset)) {
1102       GST_BUFFER_PTS (buf) += mux->output_ts_offset;
1103     }
1104   }
1105
1106   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buf))) {
1107     agg_segment->position = GST_BUFFER_PTS (buf);
1108   }
1109
1110   /* do common init (flags and streamheaders) */
1111   new_packet_common_init (mux, buf, map.data, map.size);
1112
1113   gst_buffer_unmap (buf, &map);
1114
1115   return klass->output_packet (mux, buf, new_pcr);
1116 }
1117
1118 /* called when TsMux needs new packet to write into */
1119 static void
1120 alloc_packet_cb (GstBuffer ** buf, void *user_data)
1121 {
1122   GstBaseTsMux *mux = (GstBaseTsMux *) user_data;
1123   GstBaseTsMuxClass *klass = GST_BASE_TS_MUX_GET_CLASS (mux);
1124
1125   g_assert (klass->allocate_packet);
1126
1127   klass->allocate_packet (mux, buf);
1128 }
1129
1130 static GstFlowReturn
1131 gst_base_ts_mux_aggregate_buffer (GstBaseTsMux * mux,
1132     GstAggregatorPad * agg_pad, GstBuffer * buf)
1133 {
1134   GstFlowReturn ret = GST_FLOW_OK;
1135   GstBaseTsMuxPad *best = GST_BASE_TS_MUX_PAD (agg_pad);
1136   TsMuxProgram *prog;
1137   gint64 pts = GST_CLOCK_STIME_NONE;
1138   gint64 dts = GST_CLOCK_STIME_NONE;
1139   gboolean delta = TRUE, header = FALSE;
1140   StreamData *stream_data;
1141   GstMpegtsSection *scte_section = NULL;
1142
1143   GST_DEBUG_OBJECT (mux, "Pads collected");
1144
1145   if (buf && gst_buffer_get_size (buf) == 0
1146       && GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) {
1147     gst_buffer_unref (buf);
1148     return GST_FLOW_OK;
1149   }
1150
1151   if (G_UNLIKELY (mux->first)) {
1152     ret = gst_base_ts_mux_create_streams (mux);
1153     if (G_UNLIKELY (ret != GST_FLOW_OK)) {
1154       if (buf)
1155         gst_buffer_unref (buf);
1156       return ret;
1157     }
1158
1159     mux->first = FALSE;
1160   }
1161
1162   prog = best->prog;
1163   if (prog == NULL) {
1164     GList *cur;
1165
1166     gst_base_ts_mux_create_pad_stream (mux, GST_PAD (best));
1167     tsmux_resend_pat (mux->tsmux);
1168     tsmux_resend_si (mux->tsmux);
1169     prog = best->prog;
1170     g_assert_nonnull (prog);
1171
1172     /* output PMT for each program */
1173     for (cur = mux->tsmux->programs; cur; cur = cur->next) {
1174       TsMuxProgram *program = (TsMuxProgram *) cur->data;
1175
1176       tsmux_resend_pmt (program);
1177     }
1178   }
1179
1180   g_assert (buf != NULL);
1181
1182   if (best->prepare_func) {
1183     GstBuffer *tmp;
1184
1185     tmp = best->prepare_func (buf, best, mux);
1186     g_assert (tmp);
1187     gst_buffer_unref (buf);
1188     buf = tmp;
1189   }
1190
1191   if (mux->force_key_unit_event != NULL && best->stream->is_video_stream) {
1192     GstEvent *event;
1193
1194     event = check_pending_key_unit_event (mux->force_key_unit_event,
1195         &agg_pad->segment, GST_BUFFER_PTS (buf),
1196         GST_BUFFER_FLAGS (buf), mux->pending_key_unit_ts);
1197     if (event) {
1198       GstClockTime running_time;
1199       guint count;
1200       GList *cur;
1201
1202       mux->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
1203       gst_event_replace (&mux->force_key_unit_event, NULL);
1204
1205       gst_video_event_parse_downstream_force_key_unit (event,
1206           NULL, NULL, &running_time, NULL, &count);
1207
1208       GST_INFO_OBJECT (mux, "pushing downstream force-key-unit event %d "
1209           "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
1210           GST_TIME_ARGS (running_time), count);
1211       gst_pad_push_event (GST_AGGREGATOR_SRC_PAD (mux), event);
1212
1213       /* output PAT, SI tables */
1214       tsmux_resend_pat (mux->tsmux);
1215       tsmux_resend_si (mux->tsmux);
1216
1217       /* output PMT for each program */
1218       for (cur = mux->tsmux->programs; cur; cur = cur->next) {
1219         TsMuxProgram *program = (TsMuxProgram *) cur->data;
1220
1221         tsmux_resend_pmt (program);
1222       }
1223     }
1224   }
1225
1226   if (G_UNLIKELY (prog->pcr_stream == NULL)) {
1227     /* Take the first data stream for the PCR */
1228     GST_DEBUG_OBJECT (best,
1229         "Use stream (pid=%d) from pad as PCR for program (prog_id = %d)",
1230         best->pid, best->prog_id);
1231
1232     /* Set the chosen PCR stream */
1233     tsmux_program_set_pcr_stream (prog, best->stream);
1234   }
1235
1236   GST_DEBUG_OBJECT (best, "Chose stream for output (PID: 0x%04x)", best->pid);
1237
1238   GST_OBJECT_LOCK (mux);
1239   scte_section = mux->pending_scte35_section;
1240   mux->pending_scte35_section = NULL;
1241   GST_OBJECT_UNLOCK (mux);
1242   if (G_UNLIKELY (scte_section)) {
1243     GST_DEBUG_OBJECT (mux, "Sending pending SCTE section");
1244     if (!tsmux_send_section (mux->tsmux, scte_section))
1245       GST_ERROR_OBJECT (mux, "Error sending SCTE section !");
1246   }
1247
1248   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buf))) {
1249     pts = GSTTIME_TO_MPEGTIME (GST_BUFFER_PTS (buf));
1250     GST_DEBUG_OBJECT (mux, "Buffer has PTS  %" GST_TIME_FORMAT " pts %"
1251         G_GINT64_FORMAT "%s", GST_TIME_ARGS (GST_BUFFER_PTS (buf)), pts,
1252         !GST_BUFFER_FLAG_IS_SET (buf,
1253             GST_BUFFER_FLAG_DELTA_UNIT) ? " (keyframe)" : "");
1254   }
1255
1256   if (GST_CLOCK_STIME_IS_VALID (best->dts)) {
1257     dts = GSTTIME_TO_MPEGTIME (best->dts);
1258     GST_DEBUG_OBJECT (mux, "Buffer has DTS %" GST_STIME_FORMAT " dts %"
1259         G_GINT64_FORMAT, GST_STIME_ARGS (best->dts), dts);
1260   }
1261
1262   /* should not have a DTS without PTS */
1263   if (!GST_CLOCK_STIME_IS_VALID (pts) && GST_CLOCK_STIME_IS_VALID (dts)) {
1264     GST_DEBUG_OBJECT (mux, "using DTS for unknown PTS");
1265     pts = dts;
1266   }
1267
1268   if (best->stream->is_video_stream) {
1269     delta = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
1270     header = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_HEADER);
1271   }
1272
1273   if (best->stream->is_meta && gst_buffer_get_size (buf) > (G_MAXUINT16 - 3)) {
1274     GST_WARNING_OBJECT (mux, "KLV meta unit too big, splitting not supported");
1275
1276     gst_buffer_unref (buf);
1277     return GST_FLOW_OK;
1278   }
1279
1280   GST_DEBUG_OBJECT (mux, "delta: %d", delta);
1281
1282   stream_data = stream_data_new (buf);
1283   tsmux_stream_add_data (best->stream, stream_data->map_info.data,
1284       stream_data->map_info.size, stream_data, pts, dts, !delta);
1285
1286   /* outgoing ts follows ts of PCR program stream */
1287   if (prog->pcr_stream == best->stream) {
1288     /* prefer DTS if present for PCR as it should be monotone */
1289     mux->last_ts =
1290         GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buf)) ?
1291         GST_BUFFER_DTS (buf) : GST_BUFFER_PTS (buf);
1292   }
1293
1294   mux->is_delta = delta;
1295   mux->is_header = header;
1296   while (tsmux_stream_bytes_in_buffer (best->stream) > 0) {
1297     if (!tsmux_write_stream_packet (mux->tsmux, best->stream)) {
1298       /* Failed writing data for some reason. Set appropriate error */
1299       GST_DEBUG_OBJECT (mux, "Failed to write data packet");
1300       GST_ELEMENT_ERROR (mux, STREAM, MUX,
1301           ("Failed writing output data to stream %04x", best->stream->id),
1302           (NULL));
1303       goto write_fail;
1304     }
1305   }
1306   /* flush packet cache */
1307   return gst_base_ts_mux_push_packets (mux, FALSE);
1308
1309   /* ERRORS */
1310 write_fail:
1311   {
1312     return mux->last_flow_ret;
1313   }
1314 }
1315
1316 /* GstElement implementation */
1317 static gboolean
1318 gst_base_ts_mux_has_pad_with_pid (GstBaseTsMux * mux, guint16 pid)
1319 {
1320   GList *l;
1321   gboolean res = FALSE;
1322
1323   GST_OBJECT_LOCK (mux);
1324
1325   for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
1326     GstBaseTsMuxPad *tpad = GST_BASE_TS_MUX_PAD (l->data);
1327
1328     if (tpad->pid == pid) {
1329       res = TRUE;
1330       break;
1331     }
1332   }
1333
1334   GST_OBJECT_UNLOCK (mux);
1335   return res;
1336 }
1337
1338 static GstPad *
1339 gst_base_ts_mux_request_new_pad (GstElement * element, GstPadTemplate * templ,
1340     const gchar * name, const GstCaps * caps)
1341 {
1342   GstBaseTsMux *mux = GST_BASE_TS_MUX (element);
1343   gint pid = -1;
1344   GstPad *pad = NULL;
1345   gchar *free_name = NULL;
1346
1347   if (name != NULL && sscanf (name, "sink_%d", &pid) == 1) {
1348     if (tsmux_find_stream (mux->tsmux, pid))
1349       goto stream_exists;
1350     /* Make sure we don't use reserved PID.
1351      * FIXME : This should be extended to other variants (ex: ATSC) reserved PID */
1352     if (pid < TSMUX_START_ES_PID)
1353       goto invalid_stream_pid;
1354   } else {
1355     do {
1356       pid = tsmux_get_new_pid (mux->tsmux);
1357     } while (gst_base_ts_mux_has_pad_with_pid (mux, pid));
1358
1359     /* Name the pad correctly after the selected pid */
1360     name = free_name = g_strdup_printf ("sink_%d", pid);
1361   }
1362
1363   pad = (GstPad *)
1364       GST_ELEMENT_CLASS (parent_class)->request_new_pad (element,
1365       templ, name, caps);
1366
1367   gst_base_ts_mux_pad_reset (GST_BASE_TS_MUX_PAD (pad));
1368   GST_BASE_TS_MUX_PAD (pad)->pid = pid;
1369
1370   g_free (free_name);
1371
1372   return pad;
1373
1374   /* ERRORS */
1375 stream_exists:
1376   {
1377     GST_ELEMENT_ERROR (element, STREAM, MUX, ("Duplicate PID requested"),
1378         (NULL));
1379     return NULL;
1380   }
1381
1382 invalid_stream_pid:
1383   {
1384     GST_ELEMENT_ERROR (element, STREAM, MUX,
1385         ("Invalid Elementary stream PID (0x%02u < 0x40)", pid), (NULL));
1386     return NULL;
1387   }
1388 }
1389
1390 static void
1391 gst_base_ts_mux_release_pad (GstElement * element, GstPad * pad)
1392 {
1393   GstBaseTsMux *mux = GST_BASE_TS_MUX (element);
1394
1395   if (mux->tsmux) {
1396     GList *cur;
1397     GstBaseTsMuxPad *ts_pad = GST_BASE_TS_MUX_PAD (pad);
1398     gint pid = ts_pad->pid;
1399
1400     if (ts_pad->prog) {
1401       if (ts_pad->prog->pcr_stream == ts_pad->stream) {
1402         tsmux_program_set_pcr_stream (ts_pad->prog, NULL);
1403       }
1404       if (tsmux_remove_stream (mux->tsmux, pid, ts_pad->prog)) {
1405         g_hash_table_remove (mux->programs, GINT_TO_POINTER (ts_pad->prog_id));
1406       }
1407     }
1408
1409     tsmux_resend_pat (mux->tsmux);
1410     tsmux_resend_si (mux->tsmux);
1411
1412     /* output PMT for each program */
1413     for (cur = mux->tsmux->programs; cur; cur = cur->next) {
1414       TsMuxProgram *program = (TsMuxProgram *) cur->data;
1415
1416       tsmux_resend_pmt (program);
1417     }
1418   }
1419
1420   GST_ELEMENT_CLASS (parent_class)->release_pad (element, pad);
1421 }
1422
1423 /* GstAggregator implementation */
1424
1425 static void
1426 request_keyframe (GstBaseTsMux * mux, GstClockTime running_time)
1427 {
1428   GList *l;
1429   GST_OBJECT_LOCK (mux);
1430
1431   for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
1432     gst_pad_push_event (GST_PAD (l->data),
1433         gst_video_event_new_upstream_force_key_unit (running_time, TRUE, 0));
1434   }
1435
1436   GST_OBJECT_UNLOCK (mux);
1437 }
1438
1439 static const guint32 crc_tab[256] = {
1440   0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
1441   0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1442   0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
1443   0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1444   0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
1445   0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1446   0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
1447   0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1448   0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
1449   0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1450   0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
1451   0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1452   0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
1453   0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1454   0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
1455   0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1456   0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
1457   0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1458   0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
1459   0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1460   0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
1461   0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1462   0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
1463   0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1464   0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
1465   0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1466   0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
1467   0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1468   0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
1469   0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1470   0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
1471   0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1472   0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
1473   0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1474   0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
1475   0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1476   0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
1477   0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1478   0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
1479   0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1480   0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
1481   0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1482   0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1483 };
1484
1485 static guint32
1486 _calc_crc32 (const guint8 * data, guint datalen)
1487 {
1488   gint i;
1489   guint32 crc = 0xffffffff;
1490
1491   for (i = 0; i < datalen; i++) {
1492     crc = (crc << 8) ^ crc_tab[((crc >> 24) ^ *data++) & 0xff];
1493   }
1494   return crc;
1495 }
1496
1497 #define MPEGTIME_TO_GSTTIME(t) ((t) * (guint64)100000 / 9)
1498
1499 static GstMpegtsSCTESpliceEvent *
1500 copy_splice (GstMpegtsSCTESpliceEvent * splice)
1501 {
1502   return g_boxed_copy (GST_TYPE_MPEGTS_SCTE_SPLICE_EVENT, splice);
1503 }
1504
1505 static void
1506 free_splice (GstMpegtsSCTESpliceEvent * splice)
1507 {
1508   return g_boxed_free (GST_TYPE_MPEGTS_SCTE_SPLICE_EVENT, splice);
1509 }
1510
1511 /* FIXME: get rid of this when depending on glib >= 2.62 */
1512
1513 static GPtrArray *
1514 _g_ptr_array_copy (GPtrArray * array,
1515     GCopyFunc func, GFreeFunc free_func, gpointer user_data)
1516 {
1517   GPtrArray *new_array;
1518
1519   g_return_val_if_fail (array != NULL, NULL);
1520
1521   new_array = g_ptr_array_new_with_free_func (free_func);
1522
1523   g_ptr_array_set_size (new_array, array->len);
1524
1525   if (func != NULL) {
1526     guint i;
1527
1528     for (i = 0; i < array->len; i++)
1529       new_array->pdata[i] = func (array->pdata[i], user_data);
1530   } else if (array->len > 0) {
1531     memcpy (new_array->pdata, array->pdata,
1532         array->len * sizeof (*array->pdata));
1533   }
1534
1535   new_array->len = array->len;
1536
1537   return new_array;
1538 }
1539
1540 static GstMpegtsSCTESIT *
1541 deep_copy_sit (const GstMpegtsSCTESIT * sit)
1542 {
1543   GstMpegtsSCTESIT *sit_copy = g_boxed_copy (GST_TYPE_MPEGTS_SCTE_SIT, sit);
1544   GPtrArray *splices_copy =
1545       _g_ptr_array_copy (sit_copy->splices, (GCopyFunc) copy_splice,
1546       (GFreeFunc) free_splice, NULL);
1547
1548   g_ptr_array_unref (sit_copy->splices);
1549   sit_copy->splices = splices_copy;
1550
1551   return sit_copy;
1552 }
1553
1554 /* Takes ownership of @section.
1555  *
1556  * This function is a bit complex because the SCTE sections can
1557  * have various origins:
1558  *
1559  * * Sections created by the application with the gst_mpegts_scte_*_new()
1560  *   API. The splice times / durations contained by these are expressed
1561  *   in the GStreamer running time domain, and must be translated to
1562  *   our local PES time domain. In this case, we will packetize the section
1563  *   ourselves.
1564  *
1565  * * Sections passed through from tsdemux: this case is complicated as
1566  *   splice times in the incoming stream may be encrypted, with pts_adjustment
1567  *   being the only timing field guaranteed *not* to be encrypted. In this
1568  *   case, the original binary data (section->data) will be reinjected as is
1569  *   in the output stream, with pts_adjustment adjusted. tsdemux provides us
1570  *   with the pts_offset it introduces, the difference between the original
1571  *   PES PTSs and the running times it outputs.
1572  *
1573  * Additionally, in either of these cases when the splice times aren't encrypted
1574  * we want to make use of those to request keyframes. For the passthrough case,
1575  * as the splice times are left untouched tsdemux provides us with the running
1576  * times the section originally referred to. We cannot calculate it locally
1577  * because we would need to have access to the information that the timestamps
1578  * in the original PES domain have wrapped around, and how many times they have
1579  * done so. While we could probably make educated guesses, tsdemux (more specifically
1580  * mpegtspacketizer) already keeps track of that, and it seemed more logical to
1581  * perform the calculation there and forward it alongside the downstream events.
1582  *
1583  * Finally, while we can't request keyframes at splice points in the encrypted
1584  * case, if the input stream was compliant in that regard and no reencoding took
1585  * place the splice times will still match with valid splice points, it is up
1586  * to the application to ensure that that is the case.
1587  */
1588 static void
1589 handle_scte35_section (GstBaseTsMux * mux, GstEvent * event,
1590     GstMpegtsSection * section, guint64 mpeg_pts_offset,
1591     GstStructure * rtime_map)
1592 {
1593   GstMpegtsSCTESIT *sit;
1594   guint i;
1595   gboolean forward = TRUE;
1596   guint64 pts_adjust;
1597   guint8 *section_data;
1598   guint8 *crc;
1599   gboolean translate = FALSE;
1600
1601   sit = (GstMpegtsSCTESIT *) gst_mpegts_section_get_scte_sit (section);
1602
1603   /* When the application injects manually constructed splice events,
1604    * their time domain is the GStreamer running time, we receive them
1605    * unpacketized and translate the fields in the SIT to local PTS.
1606    *
1607    * We make a copy of the SIT in order to make sure we can rewrite it.
1608    */
1609   if (sit->is_running_time) {
1610     sit = deep_copy_sit (sit);
1611     translate = TRUE;
1612   }
1613
1614   switch (sit->splice_command_type) {
1615     case GST_MTS_SCTE_SPLICE_COMMAND_NULL:
1616       /* We implement heartbeating ourselves */
1617       forward = FALSE;
1618       break;
1619     case GST_MTS_SCTE_SPLICE_COMMAND_SCHEDULE:
1620       /* No need to request keyframes at this point, splice_insert
1621        * messages will precede the future splice points and we
1622        * can request keyframes then. Only translate if needed.
1623        */
1624       if (translate) {
1625         for (i = 0; i < sit->splices->len; i++) {
1626           GstMpegtsSCTESpliceEvent *sevent =
1627               g_ptr_array_index (sit->splices, i);
1628
1629           if (sevent->program_splice_time_specified)
1630             sevent->program_splice_time =
1631                 GSTTIME_TO_MPEGTIME (sevent->program_splice_time) +
1632                 TS_MUX_CLOCK_BASE;
1633
1634           if (sevent->duration_flag)
1635             sevent->break_duration =
1636                 GSTTIME_TO_MPEGTIME (sevent->break_duration);
1637         }
1638       }
1639       break;
1640     case GST_MTS_SCTE_SPLICE_COMMAND_INSERT:
1641       /* We want keyframes at splice points */
1642       if (sit->fully_parsed && (rtime_map || translate)) {
1643
1644         for (i = 0; i < sit->splices->len; i++) {
1645           guint64 running_time = GST_CLOCK_TIME_NONE;
1646
1647           GstMpegtsSCTESpliceEvent *sevent =
1648               g_ptr_array_index (sit->splices, i);
1649           if (sevent->program_splice_time_specified) {
1650             if (rtime_map) {
1651               gchar *field_name = g_strdup_printf ("event-%u-splice-time",
1652                   sevent->splice_event_id);
1653               if (gst_structure_get_uint64 (rtime_map, field_name,
1654                       &running_time)) {
1655                 GST_DEBUG_OBJECT (mux,
1656                     "Requesting keyframe for splice point at %" GST_TIME_FORMAT,
1657                     GST_TIME_ARGS (running_time));
1658                 request_keyframe (mux, running_time);
1659               }
1660               g_free (field_name);
1661             } else {
1662               g_assert (translate == TRUE);
1663               running_time = sevent->program_splice_time;
1664               GST_DEBUG_OBJECT (mux,
1665                   "Requesting keyframe for splice point at %" GST_TIME_FORMAT,
1666                   GST_TIME_ARGS (running_time));
1667               request_keyframe (mux, running_time);
1668               sevent->program_splice_time =
1669                   GSTTIME_TO_MPEGTIME (running_time) + TS_MUX_CLOCK_BASE;
1670             }
1671           } else {
1672             GST_DEBUG_OBJECT (mux,
1673                 "Requesting keyframe for immediate splice point");
1674             request_keyframe (mux, GST_CLOCK_TIME_NONE);
1675           }
1676
1677           if (sevent->duration_flag) {
1678             if (translate) {
1679               sevent->break_duration =
1680                   GSTTIME_TO_MPEGTIME (sevent->break_duration);
1681             }
1682
1683             /* Even if auto_return is FALSE, when a break_duration is specified it
1684              * is intended as a redundancy mechanism in case the follow-up
1685              * splice insert goes missing.
1686              *
1687              * Schedule a keyframe at that point (if we can calculate its position
1688              * accurately).
1689              */
1690             if (GST_CLOCK_TIME_IS_VALID (running_time)) {
1691               running_time += MPEGTIME_TO_GSTTIME (sevent->break_duration);
1692               GST_DEBUG_OBJECT (mux,
1693                   "Requesting keyframe for end of break at %" GST_TIME_FORMAT,
1694                   GST_TIME_ARGS (running_time));
1695               request_keyframe (mux, running_time);
1696             }
1697           }
1698         }
1699       }
1700       break;
1701     case GST_MTS_SCTE_SPLICE_COMMAND_TIME:{
1702       /* Adjust timestamps and potentially request keyframes */
1703       gboolean do_request_keyframes = FALSE;
1704
1705       /* TODO: we can probably be a little more fine-tuned about determining
1706        * whether a keyframe is actually needed, but this at least takes care
1707        * of the requirement in 10.3.4 that a keyframe should not be created
1708        * when the signal contains only a time_descriptor.
1709        */
1710       if (sit->fully_parsed && (rtime_map || translate)) {
1711         for (i = 0; i < sit->descriptors->len; i++) {
1712           GstMpegtsDescriptor *descriptor =
1713               g_ptr_array_index (sit->descriptors, i);
1714
1715           switch (descriptor->tag) {
1716             case GST_MTS_SCTE_DESC_AVAIL:
1717             case GST_MTS_SCTE_DESC_DTMF:
1718             case GST_MTS_SCTE_DESC_SEGMENTATION:
1719               do_request_keyframes = TRUE;
1720               break;
1721             case GST_MTS_SCTE_DESC_TIME:
1722             case GST_MTS_SCTE_DESC_AUDIO:
1723               break;
1724           }
1725
1726           if (do_request_keyframes)
1727             break;
1728         }
1729
1730         if (sit->splice_time_specified) {
1731           GstClockTime running_time = GST_CLOCK_TIME_NONE;
1732
1733           if (rtime_map) {
1734             if (do_request_keyframes
1735                 && gst_structure_get_uint64 (rtime_map, "splice-time",
1736                     &running_time)) {
1737               GST_DEBUG_OBJECT (mux,
1738                   "Requesting keyframe for time signal at %" GST_TIME_FORMAT,
1739                   GST_TIME_ARGS (running_time));
1740               request_keyframe (mux, running_time);
1741             }
1742           } else {
1743             g_assert (translate);
1744             running_time = sit->splice_time;
1745             sit->splice_time =
1746                 GSTTIME_TO_MPEGTIME (running_time) + TS_MUX_CLOCK_BASE;
1747             if (do_request_keyframes) {
1748               GST_DEBUG_OBJECT (mux,
1749                   "Requesting keyframe for time signal at %" GST_TIME_FORMAT,
1750                   GST_TIME_ARGS (running_time));
1751               request_keyframe (mux, running_time);
1752             }
1753           }
1754         } else if (do_request_keyframes) {
1755           GST_DEBUG_OBJECT (mux,
1756               "Requesting keyframe for immediate time signal");
1757           request_keyframe (mux, GST_CLOCK_TIME_NONE);
1758         }
1759       }
1760       break;
1761     }
1762     case GST_MTS_SCTE_SPLICE_COMMAND_BANDWIDTH:
1763     case GST_MTS_SCTE_SPLICE_COMMAND_PRIVATE:
1764       /* Just let those go through untouched, none of our business */
1765       break;
1766     default:
1767       break;
1768   }
1769
1770   if (!forward) {
1771     gst_mpegts_section_unref (section);
1772     return;
1773   }
1774
1775   if (!translate) {
1776     g_assert (section->data);
1777     /* Calculate the final adjustment, as a sum of:
1778      * - The adjustment in the original packet
1779      * - The offset introduced between the original local PTS
1780      *   and the GStreamer PTS output by tsdemux
1781      * - Our own 1-hour offset
1782      */
1783     pts_adjust = sit->pts_adjustment + mpeg_pts_offset + TS_MUX_CLOCK_BASE;
1784
1785     /* Account for offsets potentially introduced between the demuxer and us */
1786     pts_adjust +=
1787         GSTTIME_TO_MPEGTIME (gst_event_get_running_time_offset (event));
1788
1789     pts_adjust &= 0x1ffffffff;
1790     section_data = g_memdup (section->data, section->section_length);
1791     section_data[4] |= pts_adjust >> 32;
1792     section_data[5] = pts_adjust >> 24;
1793     section_data[6] = pts_adjust >> 16;
1794     section_data[7] = pts_adjust >> 8;
1795     section_data[8] = pts_adjust;
1796
1797     /* Now rewrite our checksum */
1798     crc = section_data + section->section_length - 4;
1799     GST_WRITE_UINT32_BE (crc, _calc_crc32 (section_data, crc - section_data));
1800
1801     GST_OBJECT_LOCK (mux);
1802     GST_DEBUG_OBJECT (mux, "Storing SCTE section");
1803     if (mux->pending_scte35_section)
1804       gst_mpegts_section_unref (mux->pending_scte35_section);
1805     mux->pending_scte35_section =
1806         gst_mpegts_section_new (mux->scte35_pid, section_data,
1807         section->section_length);
1808     GST_OBJECT_UNLOCK (mux);
1809
1810     gst_mpegts_section_unref (section);
1811   } else {
1812     GST_OBJECT_LOCK (mux);
1813     GST_DEBUG_OBJECT (mux, "Storing SCTE section");
1814     gst_mpegts_section_unref (section);
1815     if (mux->pending_scte35_section)
1816       gst_mpegts_section_unref (mux->pending_scte35_section);
1817     mux->pending_scte35_section =
1818         gst_mpegts_section_from_scte_sit (sit, mux->scte35_pid);;
1819     GST_OBJECT_UNLOCK (mux);
1820   }
1821 }
1822
1823 static gboolean
1824 gst_base_ts_mux_send_event (GstElement * element, GstEvent * event)
1825 {
1826   GstMpegtsSection *section;
1827   GstBaseTsMux *mux = GST_BASE_TS_MUX (element);
1828
1829   section = gst_event_parse_mpegts_section (event);
1830
1831   if (section) {
1832     GST_DEBUG ("Received event with mpegts section");
1833
1834     if (section->section_type == GST_MPEGTS_SECTION_SCTE_SIT) {
1835       handle_scte35_section (mux, event, section, 0, NULL);
1836     } else {
1837       /* TODO: Check that the section type is supported */
1838       tsmux_add_mpegts_si_section (mux->tsmux, section);
1839     }
1840
1841     gst_event_unref (event);
1842
1843     return TRUE;
1844   }
1845
1846   return GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
1847 }
1848
1849 /* GstAggregator implementation */
1850
1851 static gboolean
1852 gst_base_ts_mux_sink_event (GstAggregator * agg, GstAggregatorPad * agg_pad,
1853     GstEvent * event)
1854 {
1855   GstAggregatorClass *agg_class = GST_AGGREGATOR_CLASS (parent_class);
1856   GstBaseTsMux *mux = GST_BASE_TS_MUX (agg);
1857   GstBaseTsMuxPad *ts_pad = GST_BASE_TS_MUX_PAD (agg_pad);
1858   gboolean res = FALSE;
1859   gboolean forward = TRUE;
1860
1861   switch (GST_EVENT_TYPE (event)) {
1862     case GST_EVENT_CUSTOM_DOWNSTREAM:
1863     {
1864       GstClockTime timestamp, stream_time, running_time;
1865       gboolean all_headers;
1866       guint count;
1867       const GstStructure *s;
1868
1869       s = gst_event_get_structure (event);
1870
1871       if (gst_structure_has_name (s, "scte-sit") && mux->scte35_pid != 0) {
1872
1873         /* When operating downstream of tsdemux, tsdemux will send out events
1874          * on all its source pads for each splice table it encounters. If we
1875          * are remuxing multiple streams it has demuxed, this means we could
1876          * unnecessarily repeat the same table multiple times, we avoid that
1877          * by deduplicating thanks to the event sequm
1878          */
1879         if (gst_event_get_seqnum (event) != mux->last_scte35_event_seqnum) {
1880           GstMpegtsSection *section;
1881
1882           gst_structure_get (s, "section", GST_TYPE_MPEGTS_SECTION, &section,
1883               NULL);
1884           if (section) {
1885             guint64 mpeg_pts_offset = 0;
1886             GstStructure *rtime_map = NULL;
1887
1888             gst_structure_get (s, "running-time-map", GST_TYPE_STRUCTURE,
1889                 &rtime_map, NULL);
1890             gst_structure_get_uint64 (s, "mpeg-pts-offset", &mpeg_pts_offset);
1891
1892             handle_scte35_section (mux, event, section, mpeg_pts_offset,
1893                 rtime_map);
1894             if (rtime_map)
1895               gst_structure_free (rtime_map);
1896             mux->last_scte35_event_seqnum = gst_event_get_seqnum (event);
1897           } else {
1898             GST_WARNING_OBJECT (ts_pad,
1899                 "Ignoring scte-sit event without a section");
1900           }
1901         } else {
1902           GST_DEBUG_OBJECT (ts_pad, "Ignoring duplicate scte-sit event");
1903         }
1904         res = TRUE;
1905         forward = FALSE;
1906         goto out;
1907       }
1908
1909       if (!gst_video_event_is_force_key_unit (event))
1910         goto out;
1911
1912       res = TRUE;
1913       forward = FALSE;
1914
1915       gst_video_event_parse_downstream_force_key_unit (event,
1916           &timestamp, &stream_time, &running_time, &all_headers, &count);
1917       GST_INFO_OBJECT (ts_pad, "have downstream force-key-unit event, "
1918           "seqnum %d, running-time %" GST_TIME_FORMAT " count %d",
1919           gst_event_get_seqnum (event), GST_TIME_ARGS (running_time), count);
1920
1921       if (mux->force_key_unit_event != NULL) {
1922         GST_INFO_OBJECT (mux, "skipping downstream force key unit event "
1923             "as an upstream force key unit is already queued");
1924         goto out;
1925       }
1926
1927       if (!all_headers)
1928         goto out;
1929
1930       mux->pending_key_unit_ts = running_time;
1931       gst_event_replace (&mux->force_key_unit_event, event);
1932       break;
1933     }
1934     case GST_EVENT_TAG:{
1935       GstTagList *list;
1936       gchar *lang = NULL;
1937
1938       GST_DEBUG_OBJECT (mux, "received tag event");
1939       gst_event_parse_tag (event, &list);
1940
1941       /* Matroska wants ISO 639-2B code, taglist most likely contains 639-1 */
1942       if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) {
1943         const gchar *lang_code;
1944
1945         lang_code = gst_tag_get_language_code_iso_639_2B (lang);
1946         if (lang_code) {
1947           GST_DEBUG_OBJECT (ts_pad, "Setting language to '%s'", lang_code);
1948
1949           g_free (ts_pad->language);
1950           ts_pad->language = g_strdup (lang_code);
1951         } else {
1952           GST_WARNING_OBJECT (ts_pad, "Did not get language code for '%s'",
1953               lang);
1954         }
1955         g_free (lang);
1956       }
1957
1958       /* handled this, don't want collectpads to forward it downstream */
1959       res = TRUE;
1960       forward = gst_tag_list_get_scope (list) == GST_TAG_SCOPE_GLOBAL;
1961       break;
1962     }
1963     case GST_EVENT_STREAM_START:{
1964       GstStreamFlags flags;
1965
1966       gst_event_parse_stream_flags (event, &flags);
1967
1968       /* Don't wait for data on sparse inputs like metadata streams */
1969       /*
1970          if ((flags & GST_STREAM_FLAG_SPARSE)) {
1971          GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_LOCKED);
1972          gst_collect_pads_set_waiting (pads, data, FALSE);
1973          GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_LOCKED);
1974          }
1975        */
1976       break;
1977     }
1978     default:
1979       break;
1980   }
1981
1982 out:
1983   if (!forward)
1984     gst_event_unref (event);
1985   else
1986     res = agg_class->sink_event (agg, agg_pad, event);
1987
1988   return res;
1989 }
1990
1991 static gboolean
1992 gst_base_ts_mux_src_event (GstAggregator * agg, GstEvent * event)
1993 {
1994   GstAggregatorClass *agg_class = GST_AGGREGATOR_CLASS (parent_class);
1995   GstBaseTsMux *mux = GST_BASE_TS_MUX (agg);
1996   gboolean res = TRUE, forward = TRUE;
1997
1998   switch (GST_EVENT_TYPE (event)) {
1999     case GST_EVENT_CUSTOM_UPSTREAM:
2000     {
2001       GstIterator *iter;
2002       GValue sinkpad_value = G_VALUE_INIT;
2003       GstClockTime running_time;
2004       gboolean all_headers, done = FALSE, res = FALSE;
2005       guint count;
2006
2007       if (!gst_video_event_is_force_key_unit (event))
2008         break;
2009
2010       forward = FALSE;
2011
2012       gst_video_event_parse_upstream_force_key_unit (event,
2013           &running_time, &all_headers, &count);
2014
2015       GST_INFO_OBJECT (mux, "received upstream force-key-unit event, "
2016           "seqnum %d running_time %" GST_TIME_FORMAT " all_headers %d count %d",
2017           gst_event_get_seqnum (event), GST_TIME_ARGS (running_time),
2018           all_headers, count);
2019
2020       if (!all_headers)
2021         break;
2022
2023       mux->pending_key_unit_ts = running_time;
2024       gst_event_replace (&mux->force_key_unit_event, event);
2025
2026       iter = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (mux));
2027
2028       while (!done) {
2029         switch (gst_iterator_next (iter, &sinkpad_value)) {
2030           case GST_ITERATOR_OK:{
2031             GstPad *sinkpad = g_value_get_object (&sinkpad_value);
2032             gboolean tmp;
2033
2034             GST_INFO_OBJECT (GST_AGGREGATOR_SRC_PAD (agg), "forwarding");
2035             tmp = gst_pad_push_event (sinkpad, gst_event_ref (event));
2036             GST_INFO_OBJECT (mux, "result %d", tmp);
2037             /* succeed if at least one pad succeeds */
2038             res |= tmp;
2039             break;
2040           }
2041           case GST_ITERATOR_DONE:
2042             done = TRUE;
2043             break;
2044           case GST_ITERATOR_RESYNC:
2045             gst_iterator_resync (iter);
2046             break;
2047           case GST_ITERATOR_ERROR:
2048             g_assert_not_reached ();
2049             break;
2050         }
2051         g_value_reset (&sinkpad_value);
2052       }
2053       g_value_unset (&sinkpad_value);
2054       gst_iterator_free (iter);
2055       break;
2056     }
2057     default:
2058       break;
2059   }
2060
2061   if (forward)
2062     res = agg_class->src_event (agg, event);
2063   else
2064     gst_event_unref (event);
2065
2066   return res;
2067 }
2068
2069 static GstBuffer *
2070 gst_base_ts_mux_clip (GstAggregator * agg,
2071     GstAggregatorPad * agg_pad, GstBuffer * buf)
2072 {
2073   GstBaseTsMuxPad *pad = GST_BASE_TS_MUX_PAD (agg_pad);
2074   GstClockTime time;
2075   GstBuffer *ret;
2076
2077   ret = buf;
2078
2079   /* PTS */
2080   time = GST_BUFFER_PTS (buf);
2081
2082   /* invalid left alone and passed */
2083   if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
2084     time =
2085         gst_segment_to_running_time (&agg_pad->segment, GST_FORMAT_TIME, time);
2086     if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
2087       GST_DEBUG_OBJECT (pad, "clipping buffer on pad outside segment");
2088       gst_buffer_unref (buf);
2089       ret = NULL;
2090       goto beach;
2091     } else {
2092       GST_LOG_OBJECT (pad, "buffer pts %" GST_TIME_FORMAT " ->  %"
2093           GST_TIME_FORMAT " running time",
2094           GST_TIME_ARGS (GST_BUFFER_PTS (buf)), GST_TIME_ARGS (time));
2095       buf = ret = gst_buffer_make_writable (buf);
2096       GST_BUFFER_PTS (ret) = time;
2097     }
2098   }
2099
2100   /* DTS */
2101   time = GST_BUFFER_DTS (buf);
2102
2103   /* invalid left alone and passed */
2104   if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
2105     gint sign;
2106     gint64 dts;
2107
2108     sign = gst_segment_to_running_time_full (&agg_pad->segment, GST_FORMAT_TIME,
2109         time, &time);
2110
2111     if (sign > 0)
2112       dts = (gint64) time;
2113     else
2114       dts = -((gint64) time);
2115
2116     GST_LOG_OBJECT (pad, "buffer dts %" GST_TIME_FORMAT " -> %"
2117         GST_STIME_FORMAT " running time", GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
2118         GST_STIME_ARGS (dts));
2119
2120     if (GST_CLOCK_STIME_IS_VALID (pad->dts) && dts < pad->dts) {
2121       /* Ignore DTS going backward */
2122       GST_WARNING_OBJECT (pad, "ignoring DTS going backward");
2123       dts = pad->dts;
2124     }
2125
2126     ret = gst_buffer_make_writable (buf);
2127     if (sign > 0)
2128       GST_BUFFER_DTS (ret) = time;
2129     else
2130       GST_BUFFER_DTS (ret) = GST_CLOCK_TIME_NONE;
2131
2132     pad->dts = dts;
2133   } else {
2134     pad->dts = GST_CLOCK_STIME_NONE;
2135   }
2136
2137 beach:
2138   return ret;
2139 }
2140
2141 static GstFlowReturn
2142 gst_base_ts_mux_update_src_caps (GstAggregator * agg, GstCaps * caps,
2143     GstCaps ** ret)
2144 {
2145   GstBaseTsMux *mux = GST_BASE_TS_MUX (agg);
2146   GstStructure *s;
2147
2148   *ret = gst_caps_copy (caps);
2149   s = gst_caps_get_structure (*ret, 0);
2150   gst_structure_set (s, "packetsize", G_TYPE_INT, mux->packet_size, NULL);
2151
2152   return GST_FLOW_OK;
2153 }
2154
2155 static GstBaseTsMuxPad *
2156 gst_base_ts_mux_find_best_pad (GstAggregator * aggregator)
2157 {
2158   GstBaseTsMuxPad *best = NULL;
2159   GstClockTime best_ts = GST_CLOCK_TIME_NONE;
2160   GList *l;
2161
2162   GST_OBJECT_LOCK (aggregator);
2163
2164   for (l = GST_ELEMENT_CAST (aggregator)->sinkpads; l; l = l->next) {
2165     GstBaseTsMuxPad *tpad = GST_BASE_TS_MUX_PAD (l->data);
2166     GstAggregatorPad *apad = GST_AGGREGATOR_PAD_CAST (tpad);
2167     GstBuffer *buffer;
2168
2169     buffer = gst_aggregator_pad_peek_buffer (apad);
2170     if (!buffer)
2171       continue;
2172     if (best_ts == GST_CLOCK_TIME_NONE) {
2173       best = tpad;
2174       best_ts = GST_BUFFER_DTS_OR_PTS (buffer);
2175     } else if (GST_BUFFER_DTS_OR_PTS (buffer) != GST_CLOCK_TIME_NONE) {
2176       GstClockTime t = GST_BUFFER_DTS_OR_PTS (buffer);
2177       if (t < best_ts) {
2178         best = tpad;
2179         best_ts = t;
2180       }
2181     }
2182     gst_buffer_unref (buffer);
2183   }
2184
2185   if (best)
2186     gst_object_ref (best);
2187
2188   GST_OBJECT_UNLOCK (aggregator);
2189
2190   GST_DEBUG_OBJECT (aggregator,
2191       "Best pad found with %" GST_TIME_FORMAT ": %" GST_PTR_FORMAT,
2192       GST_TIME_ARGS (best_ts), best);
2193
2194   return best;
2195 }
2196
2197 static gboolean
2198 gst_base_ts_mux_are_all_pads_eos (GstBaseTsMux * mux)
2199 {
2200   GList *l;
2201   gboolean ret = TRUE;
2202
2203   GST_OBJECT_LOCK (mux);
2204
2205   for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
2206     GstBaseTsMuxPad *pad = GST_BASE_TS_MUX_PAD (l->data);
2207
2208     if (!gst_aggregator_pad_is_eos (GST_AGGREGATOR_PAD (pad))) {
2209       ret = FALSE;
2210       break;
2211     }
2212   }
2213
2214   GST_OBJECT_UNLOCK (mux);
2215
2216   return ret;
2217 }
2218
2219
2220 static GstFlowReturn
2221 gst_base_ts_mux_aggregate (GstAggregator * agg, gboolean timeout)
2222 {
2223   GstBaseTsMux *mux = GST_BASE_TS_MUX (agg);
2224   GstFlowReturn ret = GST_FLOW_OK;
2225   GstBaseTsMuxPad *best = gst_base_ts_mux_find_best_pad (agg);
2226
2227   if (best) {
2228     GstBuffer *buffer;
2229
2230     buffer = gst_aggregator_pad_pop_buffer (GST_AGGREGATOR_PAD (best));
2231
2232     ret =
2233         gst_base_ts_mux_aggregate_buffer (GST_BASE_TS_MUX (agg),
2234         GST_AGGREGATOR_PAD (best), buffer);
2235
2236     gst_object_unref (best);
2237
2238     if (ret != GST_FLOW_OK)
2239       goto done;
2240   }
2241
2242   if (gst_base_ts_mux_are_all_pads_eos (mux)) {
2243     GstBaseTsMuxClass *klass = GST_BASE_TS_MUX_GET_CLASS (mux);
2244     /* drain some possibly cached data */
2245     if (klass->drain)
2246       klass->drain (mux);
2247     gst_base_ts_mux_push_packets (mux, TRUE);
2248
2249     ret = GST_FLOW_EOS;
2250   }
2251
2252 done:
2253   return ret;
2254 }
2255
2256 static gboolean
2257 gst_base_ts_mux_start (GstAggregator * agg)
2258 {
2259   gst_base_ts_mux_reset (GST_BASE_TS_MUX (agg), TRUE);
2260
2261   return TRUE;
2262 }
2263
2264 static gboolean
2265 gst_base_ts_mux_stop (GstAggregator * agg)
2266 {
2267   gst_base_ts_mux_reset (GST_BASE_TS_MUX (agg), TRUE);
2268
2269   return TRUE;
2270 }
2271
2272 /* GObject implementation */
2273
2274 static void
2275 gst_base_ts_mux_dispose (GObject * object)
2276 {
2277   GstBaseTsMux *mux = GST_BASE_TS_MUX (object);
2278
2279   gst_base_ts_mux_reset (mux, FALSE);
2280
2281   if (mux->out_adapter) {
2282     g_object_unref (mux->out_adapter);
2283     mux->out_adapter = NULL;
2284   }
2285   if (mux->prog_map) {
2286     gst_structure_free (mux->prog_map);
2287     mux->prog_map = NULL;
2288   }
2289   if (mux->programs) {
2290     g_hash_table_destroy (mux->programs);
2291     mux->programs = NULL;
2292   }
2293   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
2294 }
2295
2296 static void
2297 gst_base_ts_mux_constructed (GObject * object)
2298 {
2299   GstBaseTsMux *mux = GST_BASE_TS_MUX (object);
2300
2301   /* initial state */
2302   gst_base_ts_mux_reset (mux, TRUE);
2303 }
2304
2305 static void
2306 gst_base_ts_mux_set_property (GObject * object, guint prop_id,
2307     const GValue * value, GParamSpec * pspec)
2308 {
2309   GstBaseTsMux *mux = GST_BASE_TS_MUX (object);
2310   GList *l;
2311
2312   switch (prop_id) {
2313     case PROP_PROG_MAP:
2314     {
2315       const GstStructure *s = gst_value_get_structure (value);
2316       if (mux->prog_map) {
2317         gst_structure_free (mux->prog_map);
2318       }
2319       if (s)
2320         mux->prog_map = gst_structure_copy (s);
2321       else
2322         mux->prog_map = NULL;
2323       break;
2324     }
2325     case PROP_PAT_INTERVAL:
2326       mux->pat_interval = g_value_get_uint (value);
2327       if (mux->tsmux)
2328         tsmux_set_pat_interval (mux->tsmux, mux->pat_interval);
2329       break;
2330     case PROP_PMT_INTERVAL:
2331       mux->pmt_interval = g_value_get_uint (value);
2332       GST_OBJECT_LOCK (mux);
2333       for (l = GST_ELEMENT_CAST (mux)->sinkpads; l; l = l->next) {
2334         GstBaseTsMuxPad *ts_pad = GST_BASE_TS_MUX_PAD (l->data);
2335
2336         tsmux_set_pmt_interval (ts_pad->prog, mux->pmt_interval);
2337       }
2338       GST_OBJECT_UNLOCK (mux);
2339       break;
2340     case PROP_ALIGNMENT:
2341       mux->alignment = g_value_get_int (value);
2342       break;
2343     case PROP_SI_INTERVAL:
2344       mux->si_interval = g_value_get_uint (value);
2345       tsmux_set_si_interval (mux->tsmux, mux->si_interval);
2346       break;
2347     case PROP_BITRATE:
2348       mux->bitrate = g_value_get_uint64 (value);
2349       if (mux->tsmux)
2350         tsmux_set_bitrate (mux->tsmux, mux->bitrate);
2351       break;
2352     case PROP_PCR_INTERVAL:
2353       mux->pcr_interval = g_value_get_uint (value);
2354       if (mux->tsmux)
2355         tsmux_set_pcr_interval (mux->tsmux, mux->pcr_interval);
2356       break;
2357     case PROP_SCTE_35_PID:
2358       mux->scte35_pid = g_value_get_uint (value);
2359       break;
2360     case PROP_SCTE_35_NULL_INTERVAL:
2361       mux->scte35_null_interval = g_value_get_uint (value);
2362       break;
2363     default:
2364       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2365       break;
2366   }
2367 }
2368
2369 static void
2370 gst_base_ts_mux_get_property (GObject * object, guint prop_id,
2371     GValue * value, GParamSpec * pspec)
2372 {
2373   GstBaseTsMux *mux = GST_BASE_TS_MUX (object);
2374
2375   switch (prop_id) {
2376     case PROP_PROG_MAP:
2377       gst_value_set_structure (value, mux->prog_map);
2378       break;
2379     case PROP_PAT_INTERVAL:
2380       g_value_set_uint (value, mux->pat_interval);
2381       break;
2382     case PROP_PMT_INTERVAL:
2383       g_value_set_uint (value, mux->pmt_interval);
2384       break;
2385     case PROP_ALIGNMENT:
2386       g_value_set_int (value, mux->alignment);
2387       break;
2388     case PROP_SI_INTERVAL:
2389       g_value_set_uint (value, mux->si_interval);
2390       break;
2391     case PROP_BITRATE:
2392       g_value_set_uint64 (value, mux->bitrate);
2393       break;
2394     case PROP_PCR_INTERVAL:
2395       g_value_set_uint (value, mux->pcr_interval);
2396       break;
2397     case PROP_SCTE_35_PID:
2398       g_value_set_uint (value, mux->scte35_pid);
2399       break;
2400     case PROP_SCTE_35_NULL_INTERVAL:
2401       g_value_set_uint (value, mux->scte35_null_interval);
2402       break;
2403     default:
2404       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2405       break;
2406   }
2407 }
2408
2409 /* Default vmethods implementation */
2410
2411 static TsMux *
2412 gst_base_ts_mux_default_create_ts_mux (GstBaseTsMux * mux)
2413 {
2414   TsMux *tsmux = tsmux_new ();
2415   tsmux_set_write_func (tsmux, new_packet_cb, mux);
2416   tsmux_set_alloc_func (tsmux, alloc_packet_cb, mux);
2417   tsmux_set_pat_interval (tsmux, mux->pat_interval);
2418   tsmux_set_si_interval (tsmux, mux->si_interval);
2419   tsmux_set_bitrate (tsmux, mux->bitrate);
2420   tsmux_set_pcr_interval (tsmux, mux->pcr_interval);
2421
2422   return tsmux;
2423 }
2424
2425 static void
2426 gst_base_ts_mux_default_allocate_packet (GstBaseTsMux * mux,
2427     GstBuffer ** buffer)
2428 {
2429   GstBuffer *buf;
2430
2431   buf = gst_buffer_new_and_alloc (mux->packet_size);
2432
2433   *buffer = buf;
2434 }
2435
2436 static gboolean
2437 gst_base_ts_mux_default_output_packet (GstBaseTsMux * mux, GstBuffer * buffer,
2438     gint64 new_pcr)
2439 {
2440   gst_base_ts_mux_collect_packet (mux, buffer);
2441
2442   return TRUE;
2443 }
2444
2445 /* Subclass API */
2446
2447 void
2448 gst_base_ts_mux_set_packet_size (GstBaseTsMux * mux, gsize size)
2449 {
2450   mux->packet_size = size;
2451 }
2452
2453 void
2454 gst_base_ts_mux_set_automatic_alignment (GstBaseTsMux * mux, gsize alignment)
2455 {
2456   mux->automatic_alignment = alignment;
2457 }
2458
2459 static void
2460 gst_base_ts_mux_class_init (GstBaseTsMuxClass * klass)
2461 {
2462   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
2463   GstAggregatorClass *gstagg_class = GST_AGGREGATOR_CLASS (klass);
2464   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2465
2466   GST_DEBUG_CATEGORY_INIT (gst_base_ts_mux_debug, "basetsmux", 0,
2467       "MPEG Transport Stream muxer");
2468
2469   gst_element_class_set_static_metadata (gstelement_class,
2470       "MPEG Transport Stream Muxer", "Codec/Muxer",
2471       "Multiplexes media streams into an MPEG Transport Stream",
2472       "Fluendo <contact@fluendo.com>");
2473
2474   gobject_class->set_property =
2475       GST_DEBUG_FUNCPTR (gst_base_ts_mux_set_property);
2476   gobject_class->get_property =
2477       GST_DEBUG_FUNCPTR (gst_base_ts_mux_get_property);
2478   gobject_class->dispose = gst_base_ts_mux_dispose;
2479   gobject_class->constructed = gst_base_ts_mux_constructed;
2480
2481   gstelement_class->request_new_pad = gst_base_ts_mux_request_new_pad;
2482   gstelement_class->release_pad = gst_base_ts_mux_release_pad;
2483   gstelement_class->send_event = gst_base_ts_mux_send_event;
2484
2485   gstagg_class->update_src_caps = gst_base_ts_mux_update_src_caps;
2486   gstagg_class->aggregate = gst_base_ts_mux_aggregate;
2487   gstagg_class->clip = gst_base_ts_mux_clip;
2488   gstagg_class->sink_event = gst_base_ts_mux_sink_event;
2489   gstagg_class->src_event = gst_base_ts_mux_src_event;
2490   gstagg_class->start = gst_base_ts_mux_start;
2491   gstagg_class->stop = gst_base_ts_mux_stop;
2492
2493   klass->create_ts_mux = gst_base_ts_mux_default_create_ts_mux;
2494   klass->allocate_packet = gst_base_ts_mux_default_allocate_packet;
2495   klass->output_packet = gst_base_ts_mux_default_output_packet;
2496
2497   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PROG_MAP,
2498       g_param_spec_boxed ("prog-map", "Program map",
2499           "A GstStructure specifies the mapping from elementary streams to programs",
2500           GST_TYPE_STRUCTURE,
2501           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2502
2503   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PAT_INTERVAL,
2504       g_param_spec_uint ("pat-interval", "PAT interval",
2505           "Set the interval (in ticks of the 90kHz clock) for writing out the PAT table",
2506           1, G_MAXUINT, TSMUX_DEFAULT_PAT_INTERVAL,
2507           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2508
2509   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PMT_INTERVAL,
2510       g_param_spec_uint ("pmt-interval", "PMT interval",
2511           "Set the interval (in ticks of the 90kHz clock) for writing out the PMT table",
2512           1, G_MAXUINT, TSMUX_DEFAULT_PMT_INTERVAL,
2513           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2514
2515   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALIGNMENT,
2516       g_param_spec_int ("alignment", "packet alignment",
2517           "Number of packets per buffer (padded with dummy packets on EOS) "
2518           "(-1 = auto, 0 = all available packets, 7 for UDP streaming)",
2519           -1, G_MAXINT, BASETSMUX_DEFAULT_ALIGNMENT,
2520           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2521
2522   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SI_INTERVAL,
2523       g_param_spec_uint ("si-interval", "SI interval",
2524           "Set the interval (in ticks of the 90kHz clock) for writing out the Service"
2525           "Information tables", 1, G_MAXUINT, TSMUX_DEFAULT_SI_INTERVAL,
2526           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2527
2528   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BITRATE,
2529       g_param_spec_uint64 ("bitrate", "Bitrate (in bits per second)",
2530           "Set the target bitrate, will insert null packets as padding "
2531           " to achieve multiplex-wide constant bitrate (0 means no padding)",
2532           0, G_MAXUINT64, TSMUX_DEFAULT_BITRATE,
2533           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2534
2535   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PCR_INTERVAL,
2536       g_param_spec_uint ("pcr-interval", "PCR interval",
2537           "Set the interval (in ticks of the 90kHz clock) for writing PCR",
2538           1, G_MAXUINT, TSMUX_DEFAULT_PCR_INTERVAL,
2539           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2540
2541   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SCTE_35_PID,
2542       g_param_spec_uint ("scte-35-pid", "SCTE-35 PID",
2543           "PID to use for inserting SCTE-35 packets (0: unused)",
2544           0, G_MAXUINT, DEFAULT_SCTE_35_PID,
2545           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2546
2547   g_object_class_install_property (G_OBJECT_CLASS (klass),
2548       PROP_SCTE_35_NULL_INTERVAL, g_param_spec_uint ("scte-35-null-interval",
2549           "SCTE-35 NULL packet interval",
2550           "Set the interval (in ticks of the 90kHz clock) for writing SCTE-35 NULL (heartbeat) packets."
2551           " (only valid if scte-35-pid is different from 0)", 1, G_MAXUINT,
2552           TSMUX_DEFAULT_SCTE_35_NULL_INTERVAL,
2553           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
2554
2555   gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
2556       &gst_base_ts_mux_src_factory, GST_TYPE_AGGREGATOR_PAD);
2557
2558   gst_type_mark_as_plugin_api (GST_TYPE_BASE_TS_MUX_PAD, 0);
2559 }
2560
2561 static void
2562 gst_base_ts_mux_init (GstBaseTsMux * mux)
2563 {
2564   mux->out_adapter = gst_adapter_new ();
2565
2566   /* properties */
2567   mux->pat_interval = TSMUX_DEFAULT_PAT_INTERVAL;
2568   mux->pmt_interval = TSMUX_DEFAULT_PMT_INTERVAL;
2569   mux->si_interval = TSMUX_DEFAULT_SI_INTERVAL;
2570   mux->pcr_interval = TSMUX_DEFAULT_PCR_INTERVAL;
2571   mux->prog_map = NULL;
2572   mux->alignment = BASETSMUX_DEFAULT_ALIGNMENT;
2573   mux->bitrate = TSMUX_DEFAULT_BITRATE;
2574   mux->scte35_pid = DEFAULT_SCTE_35_PID;
2575   mux->scte35_null_interval = TSMUX_DEFAULT_SCTE_35_NULL_INTERVAL;
2576
2577   mux->packet_size = GST_BASE_TS_MUX_NORMAL_PACKET_LENGTH;
2578   mux->automatic_alignment = 0;
2579 }