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 4 different licenses and you
10  * can choose to use it under the terms of any one of them. The
11  * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
12  * license.
13  *
14  * MPL:
15  *
16  * The contents of this file are subject to the Mozilla Public License
17  * Version 1.1 (the "License"); you may not use this file except in
18  * compliance with the License. You may obtain a copy of the License at
19  * http://www.mozilla.org/MPL/.
20  *
21  * Software distributed under the License is distributed on an "AS IS"
22  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
23  * License for the specific language governing rights and limitations
24  * under the License.
25  *
26  * LGPL:
27  *
28  * This library is free software; you can redistribute it and/or
29  * modify it under the terms of the GNU Library General Public
30  * License as published by the Free Software Foundation; either
31  * version 2 of the License, or (at your option) any later version.
32  *
33  * This library is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
36  * Library General Public License for more details.
37  *
38  * You should have received a copy of the GNU Library General Public
39  * License along with this library; if not, write to the
40  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
41  * Boston, MA 02110-1301, USA.
42  *
43  * GPL:
44  *
45  * This program is free software; you can redistribute it and/or modify
46  * it under the terms of the GNU General Public License as published by
47  * the Free Software Foundation; either version 2 of the License, or
48  * (at your option) any later version.
49  *
50  * This program is distributed in the hope that it will be useful,
51  * but WITHOUT ANY WARRANTY; without even the implied warranty of
52  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
53  * GNU General Public License for more details.
54  *
55  * You should have received a copy of the GNU General Public License
56  * along with this program; if not, write to the Free Software
57  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
58  *
59  * MIT:
60  *
61  * Unless otherwise indicated, Source Code is licensed under MIT license.
62  * See further explanation attached in License Statement (distributed in the file
63  * LICENSE).
64  *
65  * Permission is hereby granted, free of charge, to any person obtaining a copy of
66  * this software and associated documentation files (the "Software"), to deal in
67  * the Software without restriction, including without limitation the rights to
68  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
69  * of the Software, and to permit persons to whom the Software is furnished to do
70  * so, subject to the following conditions:
71  *
72  * The above copyright notice and this permission notice shall be included in all
73  * copies or substantial portions of the Software.
74  *
75  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
77  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
78  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
81  * SOFTWARE.
82  *
83  */
84 
85 #ifdef HAVE_CONFIG_H
86 #include "config.h"
87 #endif
88 #include <stdio.h>
89 #include <string.h>
90 
91 #include <gst/tag/tag.h>
92 #include <gst/video/video.h>
93 #include <gst/mpegts/mpegts.h>
94 #include <gst/pbutils/pbutils.h>
95 
96 #include "mpegtsmux.h"
97 
98 #include "mpegtsmux_aac.h"
99 #include "mpegtsmux_ttxt.h"
100 #include "mpegtsmux_opus.h"
101 #include "mpegtsmux_jpeg2000.h"
102 #include <gst/videoparsers/gstjpeg2000parse.h>
103 #include <gst/video/video-color.h>
104 
105 GST_DEBUG_CATEGORY (mpegtsmux_debug);
106 #define GST_CAT_DEFAULT mpegtsmux_debug
107 
108 #define COLLECT_DATA_PAD(collect_data) (((GstCollectData *)(collect_data))->pad)
109 
110 enum
111 {
112   PROP_0,
113   PROP_PROG_MAP,
114   PROP_M2TS_MODE,
115   PROP_PAT_INTERVAL,
116   PROP_PMT_INTERVAL,
117   PROP_ALIGNMENT,
118   PROP_SI_INTERVAL
119 };
120 
121 #define MPEGTSMUX_DEFAULT_ALIGNMENT    -1
122 #define MPEGTSMUX_DEFAULT_M2TS         FALSE
123 
124 static GstStaticPadTemplate mpegtsmux_sink_factory =
125     GST_STATIC_PAD_TEMPLATE ("sink_%d",
126     GST_PAD_SINK,
127     GST_PAD_REQUEST,
128     GST_STATIC_CAPS ("video/mpeg, "
129         "parsed = (boolean) TRUE, "
130         "mpegversion = (int) { 1, 2, 4 }, "
131         "systemstream = (boolean) false; "
132         "video/x-dirac;"
133         "image/x-jpc;"
134         "video/x-h264,stream-format=(string)byte-stream,"
135         "alignment=(string){au, nal}; "
136         "video/x-h265,stream-format=(string)byte-stream,"
137         "alignment=(string){au, nal}; "
138         "audio/mpeg, "
139         "parsed = (boolean) TRUE, "
140         "mpegversion = (int) { 1, 2 };"
141         "audio/mpeg, "
142         "framed = (boolean) TRUE, "
143         "mpegversion = (int) 4, stream-format = (string) adts;"
144         "audio/mpeg, "
145         "mpegversion = (int) 4, stream-format = (string) raw;"
146         "audio/x-lpcm, "
147         "width = (int) { 16, 20, 24 }, "
148         "rate = (int) { 48000, 96000 }, "
149         "channels = (int) [ 1, 8 ], "
150         "dynamic_range = (int) [ 0, 255 ], "
151         "emphasis = (boolean) { FALSE, TRUE }, "
152         "mute = (boolean) { FALSE, TRUE }; "
153         "audio/x-ac3, framed = (boolean) TRUE;"
154         "audio/x-dts, framed = (boolean) TRUE;"
155         "audio/x-opus, "
156         "channels = (int) [1, 8], "
157         "channel-mapping-family = (int) {0, 1};"
158         "subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true;"
159         "image/x-jpc, profile = (int)[0, 49151];"));
160 
161 static GstStaticPadTemplate mpegtsmux_src_factory =
162 GST_STATIC_PAD_TEMPLATE ("src",
163     GST_PAD_SRC,
164     GST_PAD_ALWAYS,
165     GST_STATIC_CAPS ("video/mpegts, "
166         "systemstream = (boolean) true, " "packetsize = (int) { 188, 192} ")
167     );
168 
169 static void gst_mpegtsmux_set_property (GObject * object, guint prop_id,
170     const GValue * value, GParamSpec * pspec);
171 static void gst_mpegtsmux_get_property (GObject * object, guint prop_id,
172     GValue * value, GParamSpec * pspec);
173 
174 static void mpegtsmux_reset (MpegTsMux * mux, gboolean alloc);
175 static void mpegtsmux_dispose (GObject * object);
176 static void alloc_packet_cb (GstBuffer ** _buf, void *user_data);
177 static gboolean new_packet_cb (GstBuffer * buf, void *user_data,
178     gint64 new_pcr);
179 static void release_buffer_cb (guint8 * data, void *user_data);
180 static GstFlowReturn mpegtsmux_collect_packet (MpegTsMux * mux,
181     GstBuffer * buf);
182 static GstFlowReturn mpegtsmux_push_packets (MpegTsMux * mux, gboolean force);
183 static gboolean new_packet_m2ts (MpegTsMux * mux, GstBuffer * buf,
184     gint64 new_pcr);
185 
186 static void mpegtsmux_prepare_srcpad (MpegTsMux * mux);
187 GstFlowReturn mpegtsmux_clip_inc_running_time (GstCollectPads * pads,
188     GstCollectData * cdata, GstBuffer * buf, GstBuffer ** outbuf,
189     gpointer user_data);
190 static GstFlowReturn mpegtsmux_collected_buffer (GstCollectPads * pads,
191     GstCollectData * data, GstBuffer * buf, MpegTsMux * mux);
192 
193 static gboolean mpegtsmux_sink_event (GstCollectPads * pads,
194     GstCollectData * data, GstEvent * event, gpointer user_data);
195 static GstPad *mpegtsmux_request_new_pad (GstElement * element,
196     GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
197 static void mpegtsmux_release_pad (GstElement * element, GstPad * pad);
198 static GstStateChangeReturn mpegtsmux_change_state (GstElement * element,
199     GstStateChange transition);
200 static gboolean mpegtsmux_send_event (GstElement * element, GstEvent * event);
201 static void mpegtsmux_set_header_on_caps (MpegTsMux * mux);
202 static gboolean mpegtsmux_src_event (GstPad * pad, GstObject * parent,
203     GstEvent * event);
204 
205 #if 0
206 static void mpegtsmux_set_index (GstElement * element, GstIndex * index);
207 static GstIndex *mpegtsmux_get_index (GstElement * element);
208 
209 static GstFormat pts_format;
210 static GstFormat spn_format;
211 #endif
212 
213 typedef struct
214 {
215   GstMapInfo map_info;
216   GstBuffer *buffer;
217 } StreamData;
218 
G_DEFINE_TYPE(MpegTsMux,mpegtsmux,GST_TYPE_ELEMENT)219 G_DEFINE_TYPE (MpegTsMux, mpegtsmux, GST_TYPE_ELEMENT)
220 
221 /* Takes over the ref on the buffer */
222      static StreamData *stream_data_new (GstBuffer * buffer)
223 {
224   StreamData *res = g_new (StreamData, 1);
225   res->buffer = buffer;
226   gst_buffer_map (buffer, &(res->map_info), GST_MAP_READ);
227 
228   return res;
229 }
230 
231 static void
stream_data_free(StreamData * data)232 stream_data_free (StreamData * data)
233 {
234   if (data) {
235     gst_buffer_unmap (data->buffer, &data->map_info);
236     gst_buffer_unref (data->buffer);
237     g_free (data);
238   }
239 }
240 
241 #define parent_class mpegtsmux_parent_class
242 
243 static void
mpegtsmux_class_init(MpegTsMuxClass * klass)244 mpegtsmux_class_init (MpegTsMuxClass * klass)
245 {
246   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
247   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
248 
249   gst_element_class_add_static_pad_template (gstelement_class,
250       &mpegtsmux_sink_factory);
251   gst_element_class_add_static_pad_template (gstelement_class,
252       &mpegtsmux_src_factory);
253 
254   gst_element_class_set_static_metadata (gstelement_class,
255       "MPEG Transport Stream Muxer", "Codec/Muxer",
256       "Multiplexes media streams into an MPEG Transport Stream",
257       "Fluendo <contact@fluendo.com>");
258 
259   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_mpegtsmux_set_property);
260   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_mpegtsmux_get_property);
261   gobject_class->dispose = mpegtsmux_dispose;
262 
263   gstelement_class->request_new_pad = mpegtsmux_request_new_pad;
264   gstelement_class->release_pad = mpegtsmux_release_pad;
265   gstelement_class->change_state = mpegtsmux_change_state;
266   gstelement_class->send_event = mpegtsmux_send_event;
267 
268 #if 0
269   gstelement_class->set_index = GST_DEBUG_FUNCPTR (mpegtsmux_set_index);
270   gstelement_class->get_index = GST_DEBUG_FUNCPTR (mpegtsmux_get_index);
271 #endif
272 
273   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PROG_MAP,
274       g_param_spec_boxed ("prog-map", "Program map",
275           "A GstStructure specifies the mapping from elementary streams to programs",
276           GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
277 
278   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_M2TS_MODE,
279       g_param_spec_boolean ("m2ts-mode", "M2TS(192 bytes) Mode",
280           "Set to TRUE to output Blu-Ray disc format with 192 byte packets. "
281           "FALSE for standard TS format with 188 byte packets.",
282           MPEGTSMUX_DEFAULT_M2TS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
283 
284   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PAT_INTERVAL,
285       g_param_spec_uint ("pat-interval", "PAT interval",
286           "Set the interval (in ticks of the 90kHz clock) for writing out the PAT table",
287           1, G_MAXUINT, TSMUX_DEFAULT_PAT_INTERVAL,
288           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
289 
290   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PMT_INTERVAL,
291       g_param_spec_uint ("pmt-interval", "PMT interval",
292           "Set the interval (in ticks of the 90kHz clock) for writing out the PMT table",
293           1, G_MAXUINT, TSMUX_DEFAULT_PMT_INTERVAL,
294           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
295 
296   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ALIGNMENT,
297       g_param_spec_int ("alignment", "packet alignment",
298           "Number of packets per buffer (padded with dummy packets on EOS) "
299           "(-1 = auto, 0 = all available packets, 7 for UDP streaming)",
300           -1, G_MAXINT, MPEGTSMUX_DEFAULT_ALIGNMENT,
301           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
302 
303   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SI_INTERVAL,
304       g_param_spec_uint ("si-interval", "SI interval",
305           "Set the interval (in ticks of the 90kHz clock) for writing out the Service"
306           "Information tables", 1, G_MAXUINT, TSMUX_DEFAULT_SI_INTERVAL,
307           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
308 }
309 
310 static void
mpegtsmux_init(MpegTsMux * mux)311 mpegtsmux_init (MpegTsMux * mux)
312 {
313   mux->srcpad =
314       gst_pad_new_from_static_template (&mpegtsmux_src_factory, "src");
315   gst_pad_use_fixed_caps (mux->srcpad);
316   gst_pad_set_event_function (mux->srcpad,
317       GST_DEBUG_FUNCPTR (mpegtsmux_src_event));
318   gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
319 
320   mux->collect = gst_collect_pads_new ();
321   gst_collect_pads_set_buffer_function (mux->collect,
322       (GstCollectPadsBufferFunction)
323       GST_DEBUG_FUNCPTR (mpegtsmux_collected_buffer), mux);
324 
325   gst_collect_pads_set_event_function (mux->collect,
326       (GstCollectPadsEventFunction) GST_DEBUG_FUNCPTR (mpegtsmux_sink_event),
327       mux);
328   gst_collect_pads_set_clip_function (mux->collect, (GstCollectPadsClipFunction)
329       GST_DEBUG_FUNCPTR (mpegtsmux_clip_inc_running_time), mux);
330 
331   mux->adapter = gst_adapter_new ();
332   mux->out_adapter = gst_adapter_new ();
333 
334   /* properties */
335   mux->m2ts_mode = MPEGTSMUX_DEFAULT_M2TS;
336   mux->pat_interval = TSMUX_DEFAULT_PAT_INTERVAL;
337   mux->pmt_interval = TSMUX_DEFAULT_PMT_INTERVAL;
338   mux->si_interval = TSMUX_DEFAULT_SI_INTERVAL;
339   mux->prog_map = NULL;
340   mux->alignment = MPEGTSMUX_DEFAULT_ALIGNMENT;
341 
342   /* initial state */
343   mpegtsmux_reset (mux, TRUE);
344 }
345 
346 static void
mpegtsmux_pad_reset(MpegTsPadData * pad_data)347 mpegtsmux_pad_reset (MpegTsPadData * pad_data)
348 {
349   pad_data->dts = GST_CLOCK_STIME_NONE;
350   pad_data->prog_id = -1;
351 #if 0
352   pad_data->prog_id = -1;
353   pad_data->element_index_writer_id = -1;
354 #endif
355 
356   if (pad_data->free_func)
357     pad_data->free_func (pad_data->prepare_data);
358   pad_data->prepare_data = NULL;
359   pad_data->prepare_func = NULL;
360   pad_data->free_func = NULL;
361 
362   if (pad_data->codec_data)
363     gst_buffer_replace (&pad_data->codec_data, NULL);
364 
365   /* reference owned elsewhere */
366   pad_data->stream = NULL;
367   pad_data->prog = NULL;
368 
369   if (pad_data->language) {
370     g_free (pad_data->language);
371     pad_data->language = NULL;
372   }
373 
374 }
375 
376 static void
mpegtsmux_reset(MpegTsMux * mux,gboolean alloc)377 mpegtsmux_reset (MpegTsMux * mux, gboolean alloc)
378 {
379   GstBuffer *buf;
380   GSList *walk;
381 
382   mux->first = TRUE;
383   mux->last_flow_ret = GST_FLOW_OK;
384   mux->previous_pcr = -1;
385   mux->previous_offset = 0;
386   mux->pcr_rate_num = mux->pcr_rate_den = 1;
387   mux->last_ts = 0;
388   mux->is_delta = TRUE;
389   mux->is_header = FALSE;
390 
391   mux->streamheader_sent = FALSE;
392   mux->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
393   gst_event_replace (&mux->force_key_unit_event, NULL);
394 #if 0
395   mux->spn_count = 0;
396 
397   if (mux->element_index) {
398     gst_object_unref (mux->element_index);
399     mux->element_index = NULL;
400   }
401 #endif
402   if (mux->adapter)
403     gst_adapter_clear (mux->adapter);
404   if (mux->out_adapter)
405     gst_adapter_clear (mux->out_adapter);
406 
407   if (mux->tsmux) {
408     tsmux_free (mux->tsmux);
409     mux->tsmux = NULL;
410   }
411 
412   if (mux->programs) {
413     g_hash_table_destroy (mux->programs);
414   }
415   mux->programs = g_hash_table_new (g_direct_hash, g_direct_equal);
416 
417   while ((buf = g_queue_pop_head (&mux->streamheader)))
418     gst_buffer_unref (buf);
419 
420   gst_event_replace (&mux->force_key_unit_event, NULL);
421   gst_buffer_replace (&mux->out_buffer, NULL);
422 
423   if (mux->collect) {
424     GST_COLLECT_PADS_STREAM_LOCK (mux->collect);
425     for (walk = mux->collect->data; walk != NULL; walk = g_slist_next (walk))
426       mpegtsmux_pad_reset ((MpegTsPadData *) walk->data);
427     GST_COLLECT_PADS_STREAM_UNLOCK (mux->collect);
428   }
429 
430   if (alloc) {
431     mux->tsmux = tsmux_new ();
432     tsmux_set_write_func (mux->tsmux, new_packet_cb, mux);
433     tsmux_set_alloc_func (mux->tsmux, alloc_packet_cb, mux);
434   }
435 }
436 
437 static void
mpegtsmux_dispose(GObject * object)438 mpegtsmux_dispose (GObject * object)
439 {
440   MpegTsMux *mux = GST_MPEG_TSMUX (object);
441 
442   mpegtsmux_reset (mux, FALSE);
443 
444   if (mux->adapter) {
445     g_object_unref (mux->adapter);
446     mux->adapter = NULL;
447   }
448   if (mux->out_adapter) {
449     g_object_unref (mux->out_adapter);
450     mux->out_adapter = NULL;
451   }
452   if (mux->collect) {
453     gst_object_unref (mux->collect);
454     mux->collect = NULL;
455   }
456   if (mux->prog_map) {
457     gst_structure_free (mux->prog_map);
458     mux->prog_map = NULL;
459   }
460   if (mux->programs) {
461     g_hash_table_destroy (mux->programs);
462     mux->programs = NULL;
463   }
464   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
465 }
466 
467 static void
gst_mpegtsmux_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)468 gst_mpegtsmux_set_property (GObject * object, guint prop_id,
469     const GValue * value, GParamSpec * pspec)
470 {
471   MpegTsMux *mux = GST_MPEG_TSMUX (object);
472   GSList *walk;
473 
474   switch (prop_id) {
475     case PROP_M2TS_MODE:
476       /*set incase if the output stream need to be of 192 bytes */
477       mux->m2ts_mode = g_value_get_boolean (value);
478       break;
479     case PROP_PROG_MAP:
480     {
481       const GstStructure *s = gst_value_get_structure (value);
482       if (mux->prog_map) {
483         gst_structure_free (mux->prog_map);
484       }
485       if (s)
486         mux->prog_map = gst_structure_copy (s);
487       else
488         mux->prog_map = NULL;
489       break;
490     }
491     case PROP_PAT_INTERVAL:
492       mux->pat_interval = g_value_get_uint (value);
493       if (mux->tsmux)
494         tsmux_set_pat_interval (mux->tsmux, mux->pat_interval);
495       break;
496     case PROP_PMT_INTERVAL:
497       walk = mux->collect->data;
498       mux->pmt_interval = g_value_get_uint (value);
499 
500       while (walk) {
501         MpegTsPadData *ts_data = (MpegTsPadData *) walk->data;
502 
503         tsmux_set_pmt_interval (ts_data->prog, mux->pmt_interval);
504         walk = g_slist_next (walk);
505       }
506       break;
507     case PROP_ALIGNMENT:
508       mux->alignment = g_value_get_int (value);
509       break;
510     case PROP_SI_INTERVAL:
511       mux->si_interval = g_value_get_uint (value);
512       tsmux_set_si_interval (mux->tsmux, mux->si_interval);
513       break;
514     default:
515       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
516       break;
517   }
518 }
519 
520 static void
gst_mpegtsmux_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)521 gst_mpegtsmux_get_property (GObject * object, guint prop_id,
522     GValue * value, GParamSpec * pspec)
523 {
524   MpegTsMux *mux = GST_MPEG_TSMUX (object);
525 
526   switch (prop_id) {
527     case PROP_M2TS_MODE:
528       g_value_set_boolean (value, mux->m2ts_mode);
529       break;
530     case PROP_PROG_MAP:
531       gst_value_set_structure (value, mux->prog_map);
532       break;
533     case PROP_PAT_INTERVAL:
534       g_value_set_uint (value, mux->pat_interval);
535       break;
536     case PROP_PMT_INTERVAL:
537       g_value_set_uint (value, mux->pmt_interval);
538       break;
539     case PROP_ALIGNMENT:
540       g_value_set_int (value, mux->alignment);
541       break;
542     case PROP_SI_INTERVAL:
543       g_value_set_uint (value, mux->si_interval);
544       break;
545     default:
546       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
547       break;
548   }
549 }
550 
551 #if 0
552 static void
553 mpegtsmux_set_index (GstElement * element, GstIndex * index)
554 {
555   MpegTsMux *mux = GST_MPEG_TSMUX (element);
556 
557   GST_OBJECT_LOCK (mux);
558   if (mux->element_index)
559     gst_object_unref (mux->element_index);
560   mux->element_index = index ? gst_object_ref (index) : NULL;
561   GST_OBJECT_UNLOCK (mux);
562 
563   GST_DEBUG_OBJECT (mux, "Set index %" GST_PTR_FORMAT, mux->element_index);
564 }
565 
566 static GstIndex *
567 mpegtsmux_get_index (GstElement * element)
568 {
569   GstIndex *result = NULL;
570   MpegTsMux *mux = GST_MPEG_TSMUX (element);
571 
572   GST_OBJECT_LOCK (mux);
573   if (mux->element_index)
574     result = gst_object_ref (mux->element_index);
575   GST_OBJECT_UNLOCK (mux);
576 
577   GST_DEBUG_OBJECT (mux, "Returning index %" GST_PTR_FORMAT, result);
578 
579   return result;
580 }
581 #endif
582 
583 static void
release_buffer_cb(guint8 * data,void * user_data)584 release_buffer_cb (guint8 * data, void *user_data)
585 {
586   stream_data_free (user_data);
587 }
588 
589 static GstFlowReturn
mpegtsmux_create_stream(MpegTsMux * mux,MpegTsPadData * ts_data)590 mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
591 {
592   GstFlowReturn ret = GST_FLOW_ERROR;
593   GstCaps *caps;
594   GstStructure *s;
595   GstPad *pad;
596   TsMuxStreamType st = TSMUX_ST_RESERVED;
597   const gchar *mt;
598   const GValue *value = NULL;
599   GstBuffer *codec_data = NULL;
600   guint8 opus_channel_config_code = 0;
601   guint16 profile = 0;
602   guint8 main_level = 0;
603   guint32 max_rate = 0;
604   guint8 color_spec = 0;
605   j2k_private_data *private_data = NULL;
606 
607   pad = ts_data->collect.pad;
608   caps = gst_pad_get_current_caps (pad);
609   if (caps == NULL)
610     goto not_negotiated;
611 
612   GST_DEBUG_OBJECT (pad, "Creating stream with PID 0x%04x for caps %"
613       GST_PTR_FORMAT, ts_data->pid, caps);
614 
615   s = gst_caps_get_structure (caps, 0);
616 
617   mt = gst_structure_get_name (s);
618   value = gst_structure_get_value (s, "codec_data");
619   if (value != NULL)
620     codec_data = gst_value_get_buffer (value);
621 
622   if (strcmp (mt, "video/x-dirac") == 0) {
623     st = TSMUX_ST_VIDEO_DIRAC;
624   } else if (strcmp (mt, "audio/x-ac3") == 0) {
625     st = TSMUX_ST_PS_AUDIO_AC3;
626   } else if (strcmp (mt, "audio/x-dts") == 0) {
627     st = TSMUX_ST_PS_AUDIO_DTS;
628   } else if (strcmp (mt, "audio/x-lpcm") == 0) {
629     st = TSMUX_ST_PS_AUDIO_LPCM;
630   } else if (strcmp (mt, "video/x-h264") == 0) {
631     st = TSMUX_ST_VIDEO_H264;
632   } else if (strcmp (mt, "video/x-h265") == 0) {
633     st = TSMUX_ST_VIDEO_HEVC;
634   } else if (strcmp (mt, "audio/mpeg") == 0) {
635     gint mpegversion;
636 
637     if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
638       GST_ERROR_OBJECT (pad, "caps missing mpegversion");
639       goto not_negotiated;
640     }
641 
642     switch (mpegversion) {
643       case 1:
644         st = TSMUX_ST_AUDIO_MPEG1;
645         break;
646       case 2:
647         st = TSMUX_ST_AUDIO_MPEG2;
648         break;
649       case 4:
650       {
651         st = TSMUX_ST_AUDIO_AAC;
652         if (codec_data) {       /* TODO - Check stream format - codec data should only come with RAW stream */
653           GST_DEBUG_OBJECT (pad,
654               "we have additional codec data (%" G_GSIZE_FORMAT " bytes)",
655               gst_buffer_get_size (codec_data));
656           ts_data->codec_data = gst_buffer_ref (codec_data);
657           ts_data->prepare_func = mpegtsmux_prepare_aac;
658         } else {
659           ts_data->codec_data = NULL;
660         }
661         break;
662       }
663       default:
664         GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion);
665         goto not_negotiated;
666     }
667   } else if (strcmp (mt, "video/mpeg") == 0) {
668     gint mpegversion;
669 
670     if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
671       GST_ERROR_OBJECT (pad, "caps missing mpegversion");
672       goto not_negotiated;
673     }
674 
675     switch (mpegversion) {
676       case 1:
677         st = TSMUX_ST_VIDEO_MPEG1;
678         break;
679       case 2:
680         st = TSMUX_ST_VIDEO_MPEG2;
681         break;
682       case 4:
683         st = TSMUX_ST_VIDEO_MPEG4;
684         break;
685       default:
686         GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion);
687         goto not_negotiated;
688     }
689   } else if (strcmp (mt, "subpicture/x-dvb") == 0) {
690     st = TSMUX_ST_PS_DVB_SUBPICTURE;
691   } else if (strcmp (mt, "application/x-teletext") == 0) {
692     st = TSMUX_ST_PS_TELETEXT;
693     /* needs a particularly sized layout */
694     ts_data->prepare_func = mpegtsmux_prepare_teletext;
695   } else if (strcmp (mt, "audio/x-opus") == 0) {
696     guint8 channels, mapping_family, stream_count, coupled_count;
697     guint8 channel_mapping[256];
698 
699     if (!gst_codec_utils_opus_parse_caps (caps, NULL, &channels,
700             &mapping_family, &stream_count, &coupled_count, channel_mapping)) {
701       GST_ERROR_OBJECT (pad, "Incomplete Opus caps");
702       goto not_negotiated;
703     }
704 
705     if (channels <= 2 && mapping_family == 0) {
706       opus_channel_config_code = channels;
707     } else if (channels == 2 && mapping_family == 255 && stream_count == 1
708         && coupled_count == 1) {
709       /* Dual mono */
710       opus_channel_config_code = 0;
711     } else if (channels >= 2 && channels <= 8 && mapping_family == 1) {
712       static const guint8 coupled_stream_counts[9] = {
713         1, 0, 1, 1, 2, 2, 2, 3, 3
714       };
715       static const guint8 channel_map_a[8][8] = {
716         {0},
717         {0, 1},
718         {0, 2, 1},
719         {0, 1, 2, 3},
720         {0, 4, 1, 2, 3},
721         {0, 4, 1, 2, 3, 5},
722         {0, 4, 1, 2, 3, 5, 6},
723         {0, 6, 1, 2, 3, 4, 5, 7},
724       };
725       static const guint8 channel_map_b[8][8] = {
726         {0},
727         {0, 1},
728         {0, 1, 2},
729         {0, 1, 2, 3},
730         {0, 1, 2, 3, 4},
731         {0, 1, 2, 3, 4, 5},
732         {0, 1, 2, 3, 4, 5, 6},
733         {0, 1, 2, 3, 4, 5, 6, 7},
734       };
735 
736       /* Vorbis mapping */
737       if (stream_count == channels - coupled_stream_counts[channels] &&
738           coupled_count == coupled_stream_counts[channels] &&
739           memcmp (channel_mapping, channel_map_a[channels - 1],
740               channels) == 0) {
741         opus_channel_config_code = channels;
742       } else if (stream_count == channels - coupled_stream_counts[channels] &&
743           coupled_count == coupled_stream_counts[channels] &&
744           memcmp (channel_mapping, channel_map_b[channels - 1],
745               channels) == 0) {
746         opus_channel_config_code = channels | 0x80;
747       } else {
748         GST_FIXME_OBJECT (pad, "Opus channel mapping not handled");
749         goto not_negotiated;
750       }
751     }
752 
753     st = TSMUX_ST_PS_OPUS;
754     ts_data->prepare_func = mpegtsmux_prepare_opus;
755   } else if (strcmp (mt, "meta/x-klv") == 0) {
756     st = TSMUX_ST_PS_KLV;
757   } else if (strcmp (mt, "image/x-jpc") == 0) {
758     /*
759      * See this document for more details on standard:
760      *
761      * https://www.itu.int/rec/T-REC-H.222.0-201206-S/en
762      *  Annex S describes J2K details
763      *  Page 104 of this document describes J2k video descriptor
764      */
765 
766     const GValue *vProfile = gst_structure_get_value (s, "profile");
767     const GValue *vMainlevel = gst_structure_get_value (s, "main-level");
768     const GValue *vFramerate = gst_structure_get_value (s, "framerate");
769     const GValue *vColorimetry = gst_structure_get_value (s, "colorimetry");
770     private_data = g_new0 (j2k_private_data, 1);
771     profile = g_value_get_uint (vProfile);
772     if (profile != GST_JPEG2000_PARSE_PROFILE_BC_SINGLE) {
773       /* for now, we will relax the condition that the profile must equal GST_JPEG2000_PARSE_PROFILE_BC_SINGLE */
774       /*GST_ERROR_OBJECT (pad, "Invalid JPEG 2000 profile %d", profile);
775          goto not_negotiated; */
776     }
777     /* for now, we will relax the condition that the main level must be present */
778     if (vMainlevel) {
779       main_level = g_value_get_uint (vMainlevel);
780       if (main_level > 11) {
781         GST_ERROR_OBJECT (pad, "Invalid main level %d", main_level);
782         goto not_negotiated;
783       }
784       if (main_level >= 6) {
785         max_rate = 2 ^ (main_level - 6) * 1600 * 1000000;
786       } else {
787         switch (main_level) {
788           case 0:
789           case 1:
790           case 2:
791           case 3:
792             max_rate = 200 * 1000000;
793             break;
794           case 4:
795             max_rate = 400 * 1000000;
796             break;
797           case 5:
798             max_rate = 800 * 1000000;
799             break;
800           default:
801             break;
802         }
803       }
804     } else {
805       /*GST_ERROR_OBJECT (pad, "Missing main level");
806          goto not_negotiated; */
807     }
808     /* We always mux video in J2K-over-MPEG-TS non-interlaced mode */
809     private_data->interlace = FALSE;
810     private_data->den = 0;
811     private_data->num = 0;
812     private_data->max_bitrate = max_rate;
813     private_data->color_spec = 1;
814     /* these two fields are not used, since we always mux as non-interlaced */
815     private_data->Fic = 1;
816     private_data->Fio = 0;
817 
818     /* Get Framerate */
819     if (vFramerate != NULL) {
820       /* Data for ELSM header */
821       private_data->num = gst_value_get_fraction_numerator (vFramerate);
822       private_data->den = gst_value_get_fraction_denominator (vFramerate);
823     }
824     /* Get Colorimetry */
825     if (vColorimetry) {
826       const char *colorimetry = g_value_get_string (vColorimetry);
827       color_spec = GST_MPEGTS_JPEG2000_COLORSPEC_SRGB;  /* RGB as default */
828       if (g_str_equal (colorimetry, GST_VIDEO_COLORIMETRY_BT601)) {
829         color_spec = GST_MPEGTS_JPEG2000_COLORSPEC_REC601;
830       } else {
831         if (g_str_equal (colorimetry, GST_VIDEO_COLORIMETRY_BT709)
832             || g_str_equal (colorimetry, GST_VIDEO_COLORIMETRY_SMPTE240M)) {
833           color_spec = GST_MPEGTS_JPEG2000_COLORSPEC_REC709;
834         }
835       }
836       private_data->color_spec = color_spec;
837     } else {
838       GST_ERROR_OBJECT (pad, "Colorimetry not present in caps");
839       goto not_negotiated;
840     }
841     st = TSMUX_ST_VIDEO_JP2K;
842     ts_data->prepare_func = mpegtsmux_prepare_jpeg2000;
843     ts_data->prepare_data = private_data;
844     ts_data->free_func = mpegtsmux_free_jpeg2000;
845   }
846 
847   if (st != TSMUX_ST_RESERVED) {
848     ts_data->stream = tsmux_create_stream (mux->tsmux, st, ts_data->pid,
849         ts_data->language);
850   } else {
851     GST_DEBUG_OBJECT (pad, "Failed to determine stream type");
852   }
853 
854   if (ts_data->stream != NULL) {
855     const char *interlace_mode = gst_structure_get_string (s, "interlace-mode");
856     gst_structure_get_int (s, "rate", &ts_data->stream->audio_sampling);
857     gst_structure_get_int (s, "channels", &ts_data->stream->audio_channels);
858     gst_structure_get_int (s, "bitrate", &ts_data->stream->audio_bitrate);
859 
860     /* frame rate */
861     gst_structure_get_fraction (s, "framerate", &ts_data->stream->num,
862         &ts_data->stream->den);
863 
864     /* Interlace mode */
865     ts_data->stream->interlace_mode = FALSE;
866     if (interlace_mode) {
867       ts_data->stream->interlace_mode =
868           g_str_equal (interlace_mode, "interleaved");
869     }
870     /* Width and Height */
871     gst_structure_get_int (s, "width", &ts_data->stream->horizontal_size);
872     gst_structure_get_int (s, "height", &ts_data->stream->vertical_size);
873 
874     ts_data->stream->color_spec = color_spec;
875     ts_data->stream->max_bitrate = max_rate;
876     ts_data->stream->profile_and_level = profile | main_level;
877 
878     ts_data->stream->opus_channel_config_code = opus_channel_config_code;
879 
880     tsmux_stream_set_buffer_release_func (ts_data->stream, release_buffer_cb);
881     tsmux_program_add_stream (ts_data->prog, ts_data->stream);
882 
883     ret = GST_FLOW_OK;
884   }
885 #if 0
886   GST_OBJECT_LOCK (mux);
887   if (mux->element_index) {
888     gboolean parsed = FALSE;
889 
890     if (ts_data->stream->is_video_stream) {
891       if (gst_structure_get_boolean (s, "parsed", &parsed) && parsed) {
892         if (ts_data->element_index_writer_id == -1) {
893           gst_index_get_writer_id (mux->element_index, GST_OBJECT (mux),
894               &ts_data->element_index_writer_id);
895           GST_DEBUG_OBJECT (mux, "created GstIndex writer_id = %d for stream",
896               ts_data->element_index_writer_id);
897           gst_index_add_format (mux->element_index,
898               ts_data->element_index_writer_id, pts_format);
899           gst_index_add_format (mux->element_index,
900               ts_data->element_index_writer_id, spn_format);
901         }
902       } else {
903         GST_WARNING_OBJECT (pad, "no indexing for (unparsed) stream !");
904       }
905     }
906   }
907   GST_OBJECT_UNLOCK (mux);
908 #endif
909   gst_caps_unref (caps);
910   return ret;
911   /* ERRORS */
912 not_negotiated:
913   {
914     g_free (private_data);
915     GST_DEBUG_OBJECT (pad, "Sink pad caps were not set before pushing");
916     if (caps)
917       gst_caps_unref (caps);
918     return GST_FLOW_NOT_NEGOTIATED;
919   }
920 }
921 
922 static GstFlowReturn
mpegtsmux_create_streams(MpegTsMux * mux)923 mpegtsmux_create_streams (MpegTsMux * mux)
924 {
925   GstFlowReturn ret = GST_FLOW_OK;
926   GSList *walk = mux->collect->data;
927 
928   /* Create the streams */
929   while (walk) {
930     GstCollectData *c_data = (GstCollectData *) walk->data;
931     MpegTsPadData *ts_data = (MpegTsPadData *) walk->data;
932     gchar *name = NULL;
933     gchar *pcr_name;
934 
935     walk = g_slist_next (walk);
936 
937     if (ts_data->prog_id == -1) {
938       name = GST_PAD_NAME (c_data->pad);
939       if (mux->prog_map != NULL && gst_structure_has_field (mux->prog_map,
940               name)) {
941         gint idx;
942         gboolean ret = gst_structure_get_int (mux->prog_map, name, &idx);
943         if (!ret) {
944           GST_ELEMENT_ERROR (mux, STREAM, MUX,
945               ("Reading program map failed. Assuming default"), (NULL));
946           idx = DEFAULT_PROG_ID;
947         }
948         if (idx < 0) {
949           GST_DEBUG_OBJECT (mux, "Program number %d associate with pad %s less "
950               "than zero; DEFAULT_PROGRAM = %d is used instead",
951               idx, name, DEFAULT_PROG_ID);
952           idx = DEFAULT_PROG_ID;
953         }
954         ts_data->prog_id = idx;
955       } else {
956         ts_data->prog_id = DEFAULT_PROG_ID;
957       }
958     }
959 
960     ts_data->prog =
961         g_hash_table_lookup (mux->programs, GINT_TO_POINTER (ts_data->prog_id));
962     if (ts_data->prog == NULL) {
963       ts_data->prog = tsmux_program_new (mux->tsmux, ts_data->prog_id);
964       if (ts_data->prog == NULL)
965         goto no_program;
966       tsmux_set_pmt_interval (ts_data->prog, mux->pmt_interval);
967       g_hash_table_insert (mux->programs,
968           GINT_TO_POINTER (ts_data->prog_id), ts_data->prog);
969 
970       /* Take the first stream of the program for the PCR */
971       GST_DEBUG_OBJECT (COLLECT_DATA_PAD (ts_data),
972           "Use stream (pid=%d) from pad as PCR for program (prog_id = %d)",
973           ts_data->pid, ts_data->prog_id);
974 
975       tsmux_program_set_pcr_stream (ts_data->prog, ts_data->stream);
976     }
977 
978     if (ts_data->stream == NULL) {
979       ret = mpegtsmux_create_stream (mux, ts_data);
980       if (ret != GST_FLOW_OK)
981         goto no_stream;
982     }
983 
984     /* Check for user-specified PCR PID */
985     pcr_name = g_strdup_printf ("PCR_%d", ts_data->prog->pgm_number);
986     if (mux->prog_map && gst_structure_has_field (mux->prog_map, pcr_name)) {
987       const gchar *sink_name =
988           gst_structure_get_string (mux->prog_map, pcr_name);
989 
990       if (!g_strcmp0 (name, sink_name)) {
991         GST_DEBUG_OBJECT (mux, "User specified stream (pid=%d) as PCR for "
992             "program (prog_id = %d)", ts_data->pid, ts_data->prog->pgm_number);
993         tsmux_program_set_pcr_stream (ts_data->prog, ts_data->stream);
994       }
995     }
996     g_free (pcr_name);
997   }
998 
999   return GST_FLOW_OK;
1000 
1001   /* ERRORS */
1002 no_program:
1003   {
1004     GST_ELEMENT_ERROR (mux, STREAM, MUX,
1005         ("Could not create new program"), (NULL));
1006     return GST_FLOW_ERROR;
1007   }
1008 no_stream:
1009   {
1010     GST_ELEMENT_ERROR (mux, STREAM, MUX,
1011         ("Could not create handler for stream"), (NULL));
1012     return ret;
1013   }
1014 }
1015 
1016 static gboolean
mpegtsmux_sink_event(GstCollectPads * pads,GstCollectData * data,GstEvent * event,gpointer user_data)1017 mpegtsmux_sink_event (GstCollectPads * pads, GstCollectData * data,
1018     GstEvent * event, gpointer user_data)
1019 {
1020   MpegTsMux *mux = GST_MPEG_TSMUX (user_data);
1021   gboolean res = FALSE;
1022   gboolean forward = TRUE;
1023   MpegTsPadData *pad_data = (MpegTsPadData *) data;
1024 
1025 #ifndef GST_DISABLE_GST_DEBUG
1026   GstPad *pad;
1027 
1028   pad = data->pad;
1029 #endif
1030 
1031   switch (GST_EVENT_TYPE (event)) {
1032     case GST_EVENT_CUSTOM_DOWNSTREAM:
1033     {
1034       GstClockTime timestamp, stream_time, running_time;
1035       gboolean all_headers;
1036       guint count;
1037 
1038       if (!gst_video_event_is_force_key_unit (event))
1039         goto out;
1040 
1041       res = TRUE;
1042       forward = FALSE;
1043 
1044       gst_video_event_parse_downstream_force_key_unit (event,
1045           &timestamp, &stream_time, &running_time, &all_headers, &count);
1046       GST_INFO_OBJECT (pad, "have downstream force-key-unit event, "
1047           "seqnum %d, running-time %" GST_TIME_FORMAT " count %d",
1048           gst_event_get_seqnum (event), GST_TIME_ARGS (running_time), count);
1049 
1050       if (mux->force_key_unit_event != NULL) {
1051         GST_INFO_OBJECT (mux, "skipping downstream force key unit event "
1052             "as an upstream force key unit is already queued");
1053         goto out;
1054       }
1055 
1056       if (!all_headers)
1057         goto out;
1058 
1059       mux->pending_key_unit_ts = running_time;
1060       gst_event_replace (&mux->force_key_unit_event, event);
1061       break;
1062     }
1063     case GST_EVENT_TAG:{
1064       GstTagList *list;
1065       gchar *lang = NULL;
1066 
1067       GST_DEBUG_OBJECT (mux, "received tag event");
1068       gst_event_parse_tag (event, &list);
1069 
1070       /* Matroska wants ISO 639-2B code, taglist most likely contains 639-1 */
1071       if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) {
1072         const gchar *lang_code;
1073 
1074         lang_code = gst_tag_get_language_code_iso_639_2B (lang);
1075         if (lang_code) {
1076           GST_DEBUG_OBJECT (pad, "Setting language to '%s'", lang_code);
1077 
1078           g_free (pad_data->language);
1079           pad_data->language = g_strdup (lang_code);
1080         } else {
1081           GST_WARNING_OBJECT (pad, "Did not get language code for '%s'", lang);
1082         }
1083         g_free (lang);
1084       }
1085 
1086       /* handled this, don't want collectpads to forward it downstream */
1087       res = TRUE;
1088       forward = gst_tag_list_get_scope (list) == GST_TAG_SCOPE_GLOBAL;
1089       break;
1090     }
1091     case GST_EVENT_STREAM_START:{
1092       GstStreamFlags flags;
1093 
1094       gst_event_parse_stream_flags (event, &flags);
1095 
1096       /* Don't wait for data on sparse inputs like metadata streams */
1097       if ((flags & GST_STREAM_FLAG_SPARSE)) {
1098         GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_LOCKED);
1099         gst_collect_pads_set_waiting (pads, data, FALSE);
1100         GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_LOCKED);
1101       }
1102       break;
1103     }
1104     case GST_EVENT_FLUSH_STOP:{
1105       GList *cur;
1106 
1107       /* Send initial segments again after a flush-stop, and also resend the
1108        * header sections */
1109       mux->first = TRUE;
1110 
1111       /* output PAT, SI tables */
1112       tsmux_resend_pat (mux->tsmux);
1113       tsmux_resend_si (mux->tsmux);
1114 
1115       /* output PMT for each program */
1116       for (cur = mux->tsmux->programs; cur; cur = cur->next) {
1117         TsMuxProgram *program = (TsMuxProgram *) cur->data;
1118 
1119         tsmux_resend_pmt (program);
1120       }
1121       break;
1122     }
1123     default:
1124       break;
1125   }
1126 
1127 out:
1128   if (!forward)
1129     gst_event_unref (event);
1130   else
1131     res = gst_collect_pads_event_default (pads, data, event, FALSE);
1132 
1133   return res;
1134 }
1135 
1136 static gboolean
mpegtsmux_src_event(GstPad * pad,GstObject * parent,GstEvent * event)1137 mpegtsmux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
1138 {
1139   MpegTsMux *mux = GST_MPEG_TSMUX (parent);
1140   gboolean res = TRUE, forward = TRUE;
1141 
1142   switch (GST_EVENT_TYPE (event)) {
1143     case GST_EVENT_CUSTOM_UPSTREAM:
1144     {
1145       GstIterator *iter;
1146       GstIteratorResult iter_ret;
1147       GstPad *sinkpad;
1148       GValue sinkpad_value = G_VALUE_INIT;
1149       GstClockTime running_time;
1150       gboolean all_headers, done, res = FALSE;
1151       guint count;
1152 
1153       if (!gst_video_event_is_force_key_unit (event))
1154         break;
1155 
1156       forward = FALSE;
1157 
1158       gst_video_event_parse_upstream_force_key_unit (event,
1159           &running_time, &all_headers, &count);
1160 
1161       GST_INFO_OBJECT (mux, "received upstream force-key-unit event, "
1162           "seqnum %d running_time %" GST_TIME_FORMAT " all_headers %d count %d",
1163           gst_event_get_seqnum (event), GST_TIME_ARGS (running_time),
1164           all_headers, count);
1165 
1166       if (!all_headers)
1167         break;
1168 
1169       mux->pending_key_unit_ts = running_time;
1170       gst_event_replace (&mux->force_key_unit_event, event);
1171 
1172       iter = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (mux));
1173       done = FALSE;
1174       while (!done) {
1175         gboolean tmp;
1176 
1177         iter_ret = gst_iterator_next (iter, &sinkpad_value);
1178         sinkpad = g_value_get_object (&sinkpad_value);
1179 
1180         switch (iter_ret) {
1181           case GST_ITERATOR_DONE:
1182             done = TRUE;
1183             break;
1184           case GST_ITERATOR_OK:
1185             GST_INFO_OBJECT (pad, "forwarding");
1186             tmp = gst_pad_push_event (sinkpad, gst_event_ref (event));
1187             GST_INFO_OBJECT (mux, "result %d", tmp);
1188             /* succeed if at least one pad succeeds */
1189             res |= tmp;
1190             break;
1191           case GST_ITERATOR_ERROR:
1192             done = TRUE;
1193             break;
1194           case GST_ITERATOR_RESYNC:
1195             break;
1196         }
1197         g_value_reset (&sinkpad_value);
1198       }
1199       g_value_unset (&sinkpad_value);
1200       gst_iterator_free (iter);
1201       break;
1202     }
1203     default:
1204       break;
1205   }
1206 
1207   if (forward)
1208     res = gst_pad_event_default (pad, parent, event);
1209   else
1210     gst_event_unref (event);
1211 
1212   return res;
1213 }
1214 
1215 static GstEvent *
check_pending_key_unit_event(GstEvent * pending_event,GstSegment * segment,GstClockTime timestamp,guint flags,GstClockTime pending_key_unit_ts)1216 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
1217     GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
1218 {
1219   GstClockTime running_time, stream_time;
1220   gboolean all_headers;
1221   guint count;
1222   GstEvent *event = NULL;
1223 
1224   g_assert (segment != NULL);
1225 
1226   if (pending_event == NULL)
1227     goto out;
1228 
1229   if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
1230       timestamp == GST_CLOCK_TIME_NONE)
1231     goto out;
1232 
1233   running_time = timestamp;
1234 
1235   GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
1236       GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
1237   if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
1238       running_time < pending_key_unit_ts)
1239     goto out;
1240 
1241   if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
1242     GST_INFO ("pending force key unit, waiting for keyframe");
1243     goto out;
1244   }
1245 
1246   stream_time = gst_segment_to_stream_time (segment,
1247       GST_FORMAT_TIME, timestamp);
1248 
1249   if (GST_EVENT_TYPE (pending_event) == GST_EVENT_CUSTOM_DOWNSTREAM) {
1250     gst_video_event_parse_downstream_force_key_unit (pending_event,
1251         NULL, NULL, NULL, &all_headers, &count);
1252   } else {
1253     gst_video_event_parse_upstream_force_key_unit (pending_event, NULL,
1254         &all_headers, &count);
1255   }
1256 
1257   event =
1258       gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
1259       running_time, all_headers, count);
1260   gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
1261 
1262 out:
1263   return event;
1264 }
1265 
1266 GstFlowReturn
mpegtsmux_clip_inc_running_time(GstCollectPads * pads,GstCollectData * cdata,GstBuffer * buf,GstBuffer ** outbuf,gpointer user_data)1267 mpegtsmux_clip_inc_running_time (GstCollectPads * pads,
1268     GstCollectData * cdata, GstBuffer * buf, GstBuffer ** outbuf,
1269     gpointer user_data)
1270 {
1271   MpegTsPadData *pad_data = (MpegTsPadData *) cdata;
1272   GstClockTime time;
1273 
1274   *outbuf = buf;
1275 
1276   /* PTS */
1277   time = GST_BUFFER_PTS (buf);
1278 
1279   /* invalid left alone and passed */
1280   if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
1281     time = gst_segment_to_running_time (&cdata->segment, GST_FORMAT_TIME, time);
1282     if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
1283       GST_DEBUG_OBJECT (cdata->pad, "clipping buffer on pad outside segment");
1284       gst_buffer_unref (buf);
1285       *outbuf = NULL;
1286       goto beach;
1287     } else {
1288       GST_LOG_OBJECT (cdata->pad, "buffer pts %" GST_TIME_FORMAT " ->  %"
1289           GST_TIME_FORMAT " running time",
1290           GST_TIME_ARGS (GST_BUFFER_PTS (buf)), GST_TIME_ARGS (time));
1291       buf = *outbuf = gst_buffer_make_writable (buf);
1292       GST_BUFFER_PTS (*outbuf) = time;
1293     }
1294   }
1295 
1296   /* DTS */
1297   time = GST_BUFFER_DTS (buf);
1298 
1299   /* invalid left alone and passed */
1300   if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
1301     gint sign;
1302     gint64 dts;
1303 
1304     sign = gst_segment_to_running_time_full (&cdata->segment, GST_FORMAT_TIME,
1305         time, &time);
1306 
1307     if (sign > 0)
1308       dts = (gint64) time;
1309     else
1310       dts = -((gint64) time);
1311 
1312     GST_LOG_OBJECT (cdata->pad, "buffer dts %" GST_TIME_FORMAT " -> %"
1313         GST_STIME_FORMAT " running time", GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
1314         GST_STIME_ARGS (dts));
1315 
1316     if (GST_CLOCK_STIME_IS_VALID (pad_data->dts) && dts < pad_data->dts) {
1317       /* Ignore DTS going backward */
1318       GST_WARNING_OBJECT (cdata->pad, "ignoring DTS going backward");
1319       dts = pad_data->dts;
1320     }
1321 
1322     *outbuf = gst_buffer_make_writable (buf);
1323     if (sign > 0)
1324       GST_BUFFER_DTS (*outbuf) = time;
1325     else
1326       GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE;
1327 
1328     pad_data->dts = dts;
1329   } else {
1330     pad_data->dts = GST_CLOCK_STIME_NONE;
1331   }
1332 
1333 beach:
1334   return GST_FLOW_OK;
1335 }
1336 
1337 static GstFlowReturn
mpegtsmux_collected_buffer(GstCollectPads * pads,GstCollectData * data,GstBuffer * buf,MpegTsMux * mux)1338 mpegtsmux_collected_buffer (GstCollectPads * pads, GstCollectData * data,
1339     GstBuffer * buf, MpegTsMux * mux)
1340 {
1341   GstFlowReturn ret = GST_FLOW_OK;
1342   MpegTsPadData *best = (MpegTsPadData *) data;
1343   TsMuxProgram *prog;
1344   gint64 pts = GST_CLOCK_STIME_NONE;
1345   gint64 dts = GST_CLOCK_STIME_NONE;
1346   gboolean delta = TRUE, header = FALSE;
1347   StreamData *stream_data;
1348 
1349   GST_DEBUG_OBJECT (mux, "Pads collected");
1350 
1351   if (G_UNLIKELY (mux->first)) {
1352     ret = mpegtsmux_create_streams (mux);
1353     if (G_UNLIKELY (ret != GST_FLOW_OK)) {
1354       if (buf)
1355         gst_buffer_unref (buf);
1356       return ret;
1357     }
1358 
1359     mpegtsmux_prepare_srcpad (mux);
1360 
1361     mux->first = FALSE;
1362   }
1363 
1364   if (G_UNLIKELY (best == NULL)) {
1365     /* EOS */
1366     GST_INFO_OBJECT (mux, "EOS");
1367     /* drain some possibly cached data */
1368     new_packet_m2ts (mux, NULL, -1);
1369     mpegtsmux_push_packets (mux, TRUE);
1370     gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
1371 
1372     if (buf)
1373       gst_buffer_unref (buf);
1374 
1375     return GST_FLOW_OK;
1376   }
1377 
1378   prog = best->prog;
1379   if (prog == NULL)
1380     goto no_program;
1381 
1382   g_assert (buf != NULL);
1383 
1384   if (best->prepare_func) {
1385     GstBuffer *tmp;
1386 
1387     tmp = best->prepare_func (buf, best, mux);
1388     g_assert (tmp);
1389     gst_buffer_unref (buf);
1390     buf = tmp;
1391   }
1392 
1393   if (mux->force_key_unit_event != NULL && best->stream->is_video_stream) {
1394     GstEvent *event;
1395 
1396     event = check_pending_key_unit_event (mux->force_key_unit_event,
1397         &best->collect.segment, GST_BUFFER_PTS (buf),
1398         GST_BUFFER_FLAGS (buf), mux->pending_key_unit_ts);
1399     if (event) {
1400       GstClockTime running_time;
1401       guint count;
1402       GList *cur;
1403 
1404       mux->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
1405       gst_event_replace (&mux->force_key_unit_event, NULL);
1406 
1407       gst_video_event_parse_downstream_force_key_unit (event,
1408           NULL, NULL, &running_time, NULL, &count);
1409 
1410       GST_INFO_OBJECT (mux, "pushing downstream force-key-unit event %d "
1411           "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
1412           GST_TIME_ARGS (running_time), count);
1413       gst_pad_push_event (mux->srcpad, event);
1414 
1415       /* output PAT, SI tables */
1416       tsmux_resend_pat (mux->tsmux);
1417       tsmux_resend_si (mux->tsmux);
1418 
1419       /* output PMT for each program */
1420       for (cur = mux->tsmux->programs; cur; cur = cur->next) {
1421         TsMuxProgram *program = (TsMuxProgram *) cur->data;
1422 
1423         tsmux_resend_pmt (program);
1424       }
1425     }
1426   }
1427 
1428   if (G_UNLIKELY (prog->pcr_stream == NULL)) {
1429     /* Take the first data stream for the PCR */
1430     GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best),
1431         "Use stream (pid=%d) from pad as PCR for program (prog_id = %d)",
1432         best->pid, best->prog_id);
1433 
1434     /* Set the chosen PCR stream */
1435     tsmux_program_set_pcr_stream (prog, best->stream);
1436   }
1437 
1438   GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best),
1439       "Chose stream for output (PID: 0x%04x)", best->pid);
1440 
1441   if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buf))) {
1442     pts = GSTTIME_TO_MPEGTIME (GST_BUFFER_PTS (buf));
1443     GST_DEBUG_OBJECT (mux, "Buffer has PTS  %" GST_TIME_FORMAT " pts %"
1444         G_GINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf)), pts);
1445   }
1446 
1447   if (GST_CLOCK_STIME_IS_VALID (best->dts)) {
1448     dts = GSTTIME_TO_MPEGTIME (best->dts);
1449     GST_DEBUG_OBJECT (mux, "Buffer has DTS %" GST_STIME_FORMAT " dts %"
1450         G_GINT64_FORMAT, GST_STIME_ARGS (best->dts), dts);
1451   }
1452 
1453   /* should not have a DTS without PTS */
1454   if (!GST_CLOCK_STIME_IS_VALID (pts) && GST_CLOCK_STIME_IS_VALID (dts)) {
1455     GST_DEBUG_OBJECT (mux, "using DTS for unknown PTS");
1456     pts = dts;
1457   }
1458 
1459   if (best->stream->is_video_stream) {
1460     delta = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
1461     header = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_HEADER);
1462 #if 0
1463     GST_OBJECT_LOCK (mux);
1464     if (mux->element_index && !delta && best->element_index_writer_id != -1) {
1465       gst_index_add_association (mux->element_index,
1466           best->element_index_writer_id,
1467           GST_ASSOCIATION_FLAG_KEY_UNIT, spn_format, mux->spn_count,
1468           pts_format, pts, NULL);
1469     }
1470     GST_OBJECT_UNLOCK (mux);
1471 #endif
1472   }
1473 
1474   if (best->stream->is_meta && gst_buffer_get_size (buf) > (G_MAXUINT16 - 3)) {
1475     GST_WARNING_OBJECT (mux, "KLV meta unit too big, splitting not supported");
1476 
1477     gst_buffer_unref (buf);
1478     return GST_FLOW_OK;
1479   }
1480 
1481   GST_DEBUG_OBJECT (mux, "delta: %d", delta);
1482 
1483   stream_data = stream_data_new (buf);
1484   tsmux_stream_add_data (best->stream, stream_data->map_info.data,
1485       stream_data->map_info.size, stream_data, pts, dts, !delta);
1486 
1487   /* outgoing ts follows ts of PCR program stream */
1488   if (prog->pcr_stream == best->stream) {
1489     /* prefer DTS if present for PCR as it should be monotone */
1490     mux->last_ts =
1491         GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (buf)) ?
1492         GST_BUFFER_DTS (buf) : GST_BUFFER_PTS (buf);
1493   }
1494 
1495   mux->is_delta = delta;
1496   mux->is_header = header;
1497   while (tsmux_stream_bytes_in_buffer (best->stream) > 0) {
1498     if (!tsmux_write_stream_packet (mux->tsmux, best->stream)) {
1499       /* Failed writing data for some reason. Set appropriate error */
1500       GST_DEBUG_OBJECT (mux, "Failed to write data packet");
1501       GST_ELEMENT_ERROR (mux, STREAM, MUX,
1502           ("Failed writing output data to stream %04x", best->stream->id),
1503           (NULL));
1504       goto write_fail;
1505     }
1506   }
1507   /* flush packet cache */
1508   return mpegtsmux_push_packets (mux, FALSE);
1509 
1510   /* ERRORS */
1511 write_fail:
1512   {
1513     return mux->last_flow_ret;
1514   }
1515 no_program:
1516   {
1517     if (buf)
1518       gst_buffer_unref (buf);
1519     GST_ELEMENT_ERROR (mux, STREAM, MUX,
1520         ("Stream on pad %" GST_PTR_FORMAT
1521             " is not associated with any program", COLLECT_DATA_PAD (best)),
1522         (NULL));
1523     return GST_FLOW_ERROR;
1524   }
1525 }
1526 
1527 static GstPad *
mpegtsmux_request_new_pad(GstElement * element,GstPadTemplate * templ,const gchar * name,const GstCaps * caps)1528 mpegtsmux_request_new_pad (GstElement * element, GstPadTemplate * templ,
1529     const gchar * name, const GstCaps * caps)
1530 {
1531   MpegTsMux *mux = GST_MPEG_TSMUX (element);
1532   gint pid = -1;
1533   gchar *pad_name = NULL;
1534   GstPad *pad = NULL;
1535   MpegTsPadData *pad_data = NULL;
1536 
1537   if (name != NULL && sscanf (name, "sink_%d", &pid) == 1) {
1538     if (tsmux_find_stream (mux->tsmux, pid))
1539       goto stream_exists;
1540   } else {
1541     pid = tsmux_get_new_pid (mux->tsmux);
1542   }
1543 
1544   pad_name = g_strdup_printf ("sink_%d", pid);
1545   pad = gst_pad_new_from_template (templ, pad_name);
1546   g_free (pad_name);
1547 
1548   pad_data = (MpegTsPadData *)
1549       gst_collect_pads_add_pad (mux->collect, pad, sizeof (MpegTsPadData),
1550       (GstCollectDataDestroyNotify) (mpegtsmux_pad_reset), TRUE);
1551   if (pad_data == NULL)
1552     goto pad_failure;
1553 
1554   mpegtsmux_pad_reset (pad_data);
1555   pad_data->pid = pid;
1556 
1557   if (G_UNLIKELY (!gst_element_add_pad (element, pad)))
1558     goto could_not_add;
1559 
1560   return pad;
1561 
1562   /* ERRORS */
1563 stream_exists:
1564   {
1565     GST_ELEMENT_ERROR (element, STREAM, MUX, ("Duplicate PID requested"),
1566         (NULL));
1567     return NULL;
1568   }
1569 could_not_add:
1570   {
1571     GST_ELEMENT_ERROR (element, STREAM, FAILED,
1572         ("Internal data stream error."), ("Could not add pad to element"));
1573     gst_collect_pads_remove_pad (mux->collect, pad);
1574     gst_object_unref (pad);
1575     return NULL;
1576   }
1577 pad_failure:
1578   {
1579     GST_ELEMENT_ERROR (element, STREAM, FAILED,
1580         ("Internal data stream error."), ("Could not add pad to collectpads"));
1581     gst_object_unref (pad);
1582     return NULL;
1583   }
1584 }
1585 
1586 static void
mpegtsmux_release_pad(GstElement * element,GstPad * pad)1587 mpegtsmux_release_pad (GstElement * element, GstPad * pad)
1588 {
1589   MpegTsMux *mux = GST_MPEG_TSMUX (element);
1590 
1591   GST_DEBUG_OBJECT (mux, "Pad %" GST_PTR_FORMAT " being released", pad);
1592 
1593   if (mux->collect) {
1594     gst_collect_pads_remove_pad (mux->collect, pad);
1595   }
1596 
1597   /* chain up */
1598   gst_element_remove_pad (element, pad);
1599 }
1600 
1601 static void
new_packet_common_init(MpegTsMux * mux,GstBuffer * buf,guint8 * data,guint len)1602 new_packet_common_init (MpegTsMux * mux, GstBuffer * buf, guint8 * data,
1603     guint len)
1604 {
1605   /* Packets should be at least 188 bytes, but check anyway */
1606   g_assert (len >= 2 || !data);
1607 
1608   if (!mux->streamheader_sent && data) {
1609     guint pid = ((data[1] & 0x1f) << 8) | data[2];
1610     /* if it's a PAT or a PMT */
1611     if (pid == 0x00 || (pid >= TSMUX_START_PMT_PID && pid < TSMUX_START_ES_PID)) {
1612       GstBuffer *hbuf;
1613 
1614       if (!buf) {
1615         hbuf = gst_buffer_new_and_alloc (len);
1616         gst_buffer_fill (hbuf, 0, data, len);
1617       } else {
1618         hbuf = gst_buffer_copy (buf);
1619       }
1620       GST_LOG_OBJECT (mux,
1621           "Collecting packet with pid 0x%04x into streamheaders", pid);
1622 
1623       g_queue_push_tail (&mux->streamheader, hbuf);
1624     } else if (!g_queue_is_empty (&mux->streamheader)) {
1625       mpegtsmux_set_header_on_caps (mux);
1626       mux->streamheader_sent = TRUE;
1627     }
1628   }
1629 
1630   if (buf) {
1631     if (mux->is_header) {
1632       GST_LOG_OBJECT (mux, "marking as header buffer");
1633       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1634     }
1635     if (mux->is_delta) {
1636       GST_LOG_OBJECT (mux, "marking as delta unit");
1637       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
1638     } else {
1639       GST_DEBUG_OBJECT (mux, "marking as non-delta unit");
1640       mux->is_delta = TRUE;
1641     }
1642   }
1643 }
1644 
1645 static GstFlowReturn
mpegtsmux_push_packets(MpegTsMux * mux,gboolean force)1646 mpegtsmux_push_packets (MpegTsMux * mux, gboolean force)
1647 {
1648   GstBufferList *buffer_list;
1649   gint align = mux->alignment;
1650   gint av, packet_size;
1651 
1652   if (mux->m2ts_mode) {
1653     packet_size = M2TS_PACKET_LENGTH;
1654     if (align < 0)
1655       align = 32;
1656   } else {
1657     packet_size = NORMAL_TS_PACKET_LENGTH;
1658     if (align < 0)
1659       align = 0;
1660   }
1661 
1662   av = gst_adapter_available (mux->out_adapter);
1663   GST_LOG_OBJECT (mux, "align %d, av %d", align, av);
1664 
1665   if (av == 0)
1666     return GST_FLOW_OK;
1667 
1668   /* no alignment, just push all available data */
1669   if (align == 0) {
1670     buffer_list = gst_adapter_take_buffer_list (mux->out_adapter, av);
1671     return gst_pad_push_list (mux->srcpad, buffer_list);
1672   }
1673 
1674   align *= packet_size;
1675 
1676   if (!force && align > av)
1677     return GST_FLOW_OK;
1678 
1679   buffer_list = gst_buffer_list_new_sized ((av / align) + 1);
1680 
1681   GST_LOG_OBJECT (mux, "aligning to %d bytes", align);
1682   while (align <= av) {
1683     GstBuffer *buf;
1684     GstClockTime pts;
1685 
1686     pts = gst_adapter_prev_pts (mux->out_adapter, NULL);
1687     buf = gst_adapter_take_buffer (mux->out_adapter, align);
1688 
1689     GST_BUFFER_PTS (buf) = pts;
1690 
1691     gst_buffer_list_add (buffer_list, buf);
1692     av -= align;
1693   }
1694 
1695   if (av > 0 && force) {
1696     GstBuffer *buf;
1697     GstClockTime pts;
1698     guint8 *data;
1699     guint32 header;
1700     gint dummy;
1701     GstMapInfo map;
1702 
1703     GST_LOG_OBJECT (mux, "handling %d leftover bytes", av);
1704 
1705     pts = gst_adapter_prev_pts (mux->out_adapter, NULL);
1706     buf = gst_buffer_new_and_alloc (align);
1707 
1708     GST_BUFFER_PTS (buf) = pts;
1709 
1710     gst_buffer_map (buf, &map, GST_MAP_READ);
1711     data = map.data;
1712 
1713     gst_adapter_copy (mux->out_adapter, data, 0, av);
1714     gst_adapter_clear (mux->out_adapter);
1715 
1716     data += av;
1717     header = GST_READ_UINT32_BE (data - packet_size);
1718 
1719     dummy = (map.size - av) / packet_size;
1720     GST_LOG_OBJECT (mux, "adding %d null packets", dummy);
1721 
1722     for (; dummy > 0; dummy--) {
1723       gint offset;
1724 
1725       if (packet_size > NORMAL_TS_PACKET_LENGTH) {
1726         GST_WRITE_UINT32_BE (data, header);
1727         /* simply increase header a bit and never mind too much */
1728         header++;
1729         offset = 4;
1730       } else {
1731         offset = 0;
1732       }
1733       GST_WRITE_UINT8 (data + offset, TSMUX_SYNC_BYTE);
1734       /* null packet PID */
1735       GST_WRITE_UINT16_BE (data + offset + 1, 0x1FFF);
1736       /* no adaptation field exists | continuity counter undefined */
1737       GST_WRITE_UINT8 (data + offset + 3, 0x10);
1738       /* payload */
1739       memset (data + offset + 4, 0, NORMAL_TS_PACKET_LENGTH - 4);
1740       data += packet_size;
1741     }
1742 
1743     gst_buffer_unmap (buf, &map);
1744     gst_buffer_list_add (buffer_list, buf);
1745   }
1746 
1747   return gst_pad_push_list (mux->srcpad, buffer_list);
1748 }
1749 
1750 static GstFlowReturn
mpegtsmux_collect_packet(MpegTsMux * mux,GstBuffer * buf)1751 mpegtsmux_collect_packet (MpegTsMux * mux, GstBuffer * buf)
1752 {
1753   GST_LOG_OBJECT (mux, "collecting packet size %" G_GSIZE_FORMAT,
1754       gst_buffer_get_size (buf));
1755   gst_adapter_push (mux->out_adapter, buf);
1756 
1757   return GST_FLOW_OK;
1758 }
1759 
1760 static gboolean
new_packet_m2ts(MpegTsMux * mux,GstBuffer * buf,gint64 new_pcr)1761 new_packet_m2ts (MpegTsMux * mux, GstBuffer * buf, gint64 new_pcr)
1762 {
1763   GstBuffer *out_buf;
1764   int chunk_bytes;
1765   GstMapInfo map;
1766 
1767   GST_LOG_OBJECT (mux, "Have buffer %p with new_pcr=%" G_GINT64_FORMAT,
1768       buf, new_pcr);
1769 
1770   chunk_bytes = gst_adapter_available (mux->adapter);
1771 
1772   if (G_LIKELY (buf)) {
1773     if (new_pcr < 0) {
1774       /* If there is no pcr in current ts packet then just add the packet
1775          to the adapter for later output when we see a PCR */
1776       GST_LOG_OBJECT (mux, "Accumulating non-PCR packet");
1777       gst_adapter_push (mux->adapter, buf);
1778       goto exit;
1779     }
1780 
1781     /* no first interpolation point yet, then this is the one,
1782      * otherwise it is the second interpolation point */
1783     if (mux->previous_pcr < 0 && chunk_bytes) {
1784       mux->previous_pcr = new_pcr;
1785       mux->previous_offset = chunk_bytes;
1786       GST_LOG_OBJECT (mux, "Accumulating non-PCR packet");
1787       gst_adapter_push (mux->adapter, buf);
1788       goto exit;
1789     }
1790   } else {
1791     g_assert (new_pcr == -1);
1792   }
1793 
1794   /* interpolate if needed, and 2 points available */
1795   if (chunk_bytes && (new_pcr != mux->previous_pcr)) {
1796     gint64 offset = 0;
1797 
1798     GST_LOG_OBJECT (mux, "Processing pending packets; "
1799         "previous pcr %" G_GINT64_FORMAT ", previous offset %d, "
1800         "current pcr %" G_GINT64_FORMAT ", current offset %d",
1801         mux->previous_pcr, (gint) mux->previous_offset,
1802         new_pcr, (gint) chunk_bytes);
1803 
1804     g_assert (chunk_bytes > mux->previous_offset);
1805     /* if draining, use previous rate */
1806     if (G_LIKELY (new_pcr > 0)) {
1807       mux->pcr_rate_num = new_pcr - mux->previous_pcr;
1808       mux->pcr_rate_den = chunk_bytes - mux->previous_offset;
1809     }
1810 
1811     while (offset < chunk_bytes) {
1812       guint64 cur_pcr, ts;
1813 
1814       /* Loop, pulling packets of the adapter, updating their 4 byte
1815        * timestamp header and pushing */
1816 
1817       /* interpolate PCR */
1818       if (G_LIKELY (offset >= mux->previous_offset))
1819         cur_pcr = mux->previous_pcr +
1820             gst_util_uint64_scale (offset - mux->previous_offset,
1821             mux->pcr_rate_num, mux->pcr_rate_den);
1822       else
1823         cur_pcr = mux->previous_pcr -
1824             gst_util_uint64_scale (mux->previous_offset - offset,
1825             mux->pcr_rate_num, mux->pcr_rate_den);
1826 
1827       /* FIXME: what about DTS here? */
1828       ts = gst_adapter_prev_pts (mux->adapter, NULL);
1829       out_buf = gst_adapter_take_buffer (mux->adapter, M2TS_PACKET_LENGTH);
1830       g_assert (out_buf);
1831       offset += M2TS_PACKET_LENGTH;
1832 
1833       GST_BUFFER_PTS (out_buf) = ts;
1834 
1835       gst_buffer_map (out_buf, &map, GST_MAP_WRITE);
1836 
1837       /* The header is the bottom 30 bits of the PCR, apparently not
1838        * encoded into base + ext as in the packets themselves */
1839       GST_WRITE_UINT32_BE (map.data, cur_pcr & 0x3FFFFFFF);
1840       gst_buffer_unmap (out_buf, &map);
1841 
1842       GST_LOG_OBJECT (mux, "Outputting a packet of length %d PCR %"
1843           G_GUINT64_FORMAT, M2TS_PACKET_LENGTH, cur_pcr);
1844       mpegtsmux_collect_packet (mux, out_buf);
1845     }
1846   }
1847 
1848   if (G_UNLIKELY (!buf))
1849     goto exit;
1850 
1851   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1852 
1853   /* Finally, output the passed in packet */
1854   /* Only write the bottom 30 bits of the PCR */
1855   GST_WRITE_UINT32_BE (map.data, new_pcr & 0x3FFFFFFF);
1856 
1857   gst_buffer_unmap (buf, &map);
1858 
1859   GST_LOG_OBJECT (mux, "Outputting a packet of length %d PCR %"
1860       G_GUINT64_FORMAT, M2TS_PACKET_LENGTH, new_pcr);
1861   mpegtsmux_collect_packet (mux, buf);
1862 
1863   if (new_pcr != mux->previous_pcr) {
1864     mux->previous_pcr = new_pcr;
1865     mux->previous_offset = -M2TS_PACKET_LENGTH;
1866   }
1867 
1868 exit:
1869   return TRUE;
1870 }
1871 
1872 /* Called when the TsMux has prepared a packet for output. Return FALSE
1873  * on error */
1874 static gboolean
new_packet_cb(GstBuffer * buf,void * user_data,gint64 new_pcr)1875 new_packet_cb (GstBuffer * buf, void *user_data, gint64 new_pcr)
1876 {
1877   MpegTsMux *mux = (MpegTsMux *) user_data;
1878   gint offset = 0;
1879   GstMapInfo map;
1880 
1881 #if 0
1882   GST_LOG_OBJECT (mux, "handling packet %d", mux->spn_count);
1883   mux->spn_count++;
1884 #endif
1885 
1886   if (mux->m2ts_mode) {
1887     offset = 4;
1888     gst_buffer_set_size (buf, NORMAL_TS_PACKET_LENGTH + offset);
1889   }
1890 
1891   gst_buffer_map (buf, &map, GST_MAP_READWRITE);
1892 
1893   if (offset) {
1894     /* there should be a better way to do this */
1895     memmove (map.data + offset, map.data, map.size - offset);
1896   }
1897 
1898   GST_BUFFER_PTS (buf) = mux->last_ts;
1899   /* do common init (flags and streamheaders) */
1900   new_packet_common_init (mux, buf, map.data + offset, map.size);
1901 
1902   gst_buffer_unmap (buf, &map);
1903 
1904   /* all is meant for downstream, including any prefix */
1905   if (offset)
1906     return new_packet_m2ts (mux, buf, new_pcr);
1907   else
1908     mpegtsmux_collect_packet (mux, buf);
1909 
1910   return TRUE;
1911 }
1912 
1913 /* called when TsMux needs new packet to write into */
1914 static void
alloc_packet_cb(GstBuffer ** _buf,void * user_data)1915 alloc_packet_cb (GstBuffer ** _buf, void *user_data)
1916 {
1917   MpegTsMux *mux = (MpegTsMux *) user_data;
1918   GstBuffer *buf;
1919   gint offset = 0;
1920 
1921   if (mux->m2ts_mode == TRUE)
1922     offset = 4;
1923 
1924   buf = gst_buffer_new_and_alloc (NORMAL_TS_PACKET_LENGTH + offset);
1925   gst_buffer_set_size (buf, NORMAL_TS_PACKET_LENGTH);
1926 
1927   *_buf = buf;
1928 }
1929 
1930 static void
mpegtsmux_set_header_on_caps(MpegTsMux * mux)1931 mpegtsmux_set_header_on_caps (MpegTsMux * mux)
1932 {
1933   GstBuffer *buf;
1934   GstStructure *structure;
1935   GValue array = { 0 };
1936   GValue value = { 0 };
1937   GstCaps *caps;
1938 
1939   caps = gst_caps_make_writable (gst_pad_get_current_caps (mux->srcpad));
1940   structure = gst_caps_get_structure (caps, 0);
1941 
1942   g_value_init (&array, GST_TYPE_ARRAY);
1943 
1944   GST_LOG_OBJECT (mux, "setting %u packets into streamheader",
1945       g_queue_get_length (&mux->streamheader));
1946 
1947   while ((buf = g_queue_pop_head (&mux->streamheader))) {
1948     g_value_init (&value, GST_TYPE_BUFFER);
1949     gst_value_take_buffer (&value, buf);
1950     gst_value_array_append_value (&array, &value);
1951     g_value_unset (&value);
1952   }
1953 
1954   gst_structure_set_value (structure, "streamheader", &array);
1955   gst_pad_set_caps (mux->srcpad, caps);
1956   g_value_unset (&array);
1957   gst_caps_unref (caps);
1958 }
1959 
1960 static void
mpegtsmux_prepare_srcpad(MpegTsMux * mux)1961 mpegtsmux_prepare_srcpad (MpegTsMux * mux)
1962 {
1963   GstSegment seg;
1964   /* we are not going to seek */
1965   GstEvent *new_seg;
1966   gchar s_id[32];
1967   GstCaps *caps = gst_caps_new_simple ("video/mpegts",
1968       "systemstream", G_TYPE_BOOLEAN, TRUE,
1969       "packetsize", G_TYPE_INT,
1970       (mux->m2ts_mode ? M2TS_PACKET_LENGTH : NORMAL_TS_PACKET_LENGTH),
1971       NULL);
1972 
1973   /* stream-start (FIXME: create id based on input ids) */
1974   g_snprintf (s_id, sizeof (s_id), "mpegtsmux-%08x", g_random_int ());
1975   gst_pad_push_event (mux->srcpad, gst_event_new_stream_start (s_id));
1976 
1977   gst_segment_init (&seg, GST_FORMAT_TIME);
1978   new_seg = gst_event_new_segment (&seg);
1979 
1980   /* Set caps on src pad from our template and push new segment */
1981   gst_pad_set_caps (mux->srcpad, caps);
1982   gst_caps_unref (caps);
1983 
1984   if (!gst_pad_push_event (mux->srcpad, new_seg)) {
1985     GST_WARNING_OBJECT (mux, "New segment event was not handled downstream");
1986   }
1987 }
1988 
1989 static GstStateChangeReturn
mpegtsmux_change_state(GstElement * element,GstStateChange transition)1990 mpegtsmux_change_state (GstElement * element, GstStateChange transition)
1991 {
1992   MpegTsMux *mux = GST_MPEG_TSMUX (element);
1993   GstStateChangeReturn ret;
1994 
1995   switch (transition) {
1996     case GST_STATE_CHANGE_NULL_TO_READY:
1997       break;
1998     case GST_STATE_CHANGE_READY_TO_PAUSED:
1999       gst_collect_pads_start (mux->collect);
2000       break;
2001     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2002       break;
2003     case GST_STATE_CHANGE_PAUSED_TO_READY:
2004       gst_collect_pads_stop (mux->collect);
2005       break;
2006     case GST_STATE_CHANGE_READY_TO_NULL:
2007       break;
2008     default:
2009       break;
2010   }
2011 
2012   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2013 
2014   switch (transition) {
2015     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2016       break;
2017     case GST_STATE_CHANGE_PAUSED_TO_READY:
2018       mpegtsmux_reset (mux, TRUE);
2019       break;
2020     case GST_STATE_CHANGE_READY_TO_NULL:
2021       break;
2022     default:
2023       break;
2024   }
2025 
2026   return ret;
2027 }
2028 
2029 static gboolean
mpegtsmux_send_event(GstElement * element,GstEvent * event)2030 mpegtsmux_send_event (GstElement * element, GstEvent * event)
2031 {
2032   GstMpegtsSection *section;
2033   MpegTsMux *mux = GST_MPEG_TSMUX (element);
2034 
2035   section = gst_event_parse_mpegts_section (event);
2036   gst_event_unref (event);
2037 
2038   if (section) {
2039     GST_DEBUG ("Received event with mpegts section");
2040 
2041     /* TODO: Check that the section type is supported */
2042     tsmux_add_mpegts_si_section (mux->tsmux, section);
2043 
2044     return TRUE;
2045   }
2046 
2047   return FALSE;
2048 }
2049 
2050 static gboolean
plugin_init(GstPlugin * plugin)2051 plugin_init (GstPlugin * plugin)
2052 {
2053   gst_mpegts_initialize ();
2054   if (!gst_element_register (plugin, "mpegtsmux", GST_RANK_PRIMARY,
2055           mpegtsmux_get_type ()))
2056     return FALSE;
2057 
2058   GST_DEBUG_CATEGORY_INIT (mpegtsmux_debug, "mpegtsmux", 0,
2059       "MPEG Transport Stream muxer");
2060 
2061   return TRUE;
2062 }
2063 
2064 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
2065     mpegtsmux, "MPEG-TS muxer",
2066     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
2067