2 * Copyright 2006 BBC and Fluendo S.A.
4 * This library is licensed under 4 different licenses and you
5 * can choose to use it under the terms of any one of them. The
6 * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
11 * The contents of this file are subject to the Mozilla Public License
12 * Version 1.1 (the "License"); you may not use this file except in
13 * compliance with the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/.
16 * Software distributed under the License is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 * License for the specific language governing rights and limitations
23 * This library is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU Library General Public
25 * License as published by the Free Software Foundation; either
26 * version 2 of the License, or (at your option) any later version.
28 * This library is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 * Library General Public License for more details.
33 * You should have received a copy of the GNU Library General Public
34 * License along with this library; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
40 * This program is free software; you can redistribute it and/or modify
41 * it under the terms of the GNU General Public License as published by
42 * the Free Software Foundation; either version 2 of the License, or
43 * (at your option) any later version.
45 * This program is distributed in the hope that it will be useful,
46 * but WITHOUT ANY WARRANTY; without even the implied warranty of
47 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 * GNU General Public License for more details.
50 * You should have received a copy of the GNU General Public License
51 * along with this program; if not, write to the Free Software
52 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
56 * Unless otherwise indicated, Source Code is licensed under MIT license.
57 * See further explanation attached in License Statement (distributed in the file
60 * Permission is hereby granted, free of charge, to any person obtaining a copy of
61 * this software and associated documentation files (the "Software"), to deal in
62 * the Software without restriction, including without limitation the rights to
63 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
64 * of the Software, and to permit persons to whom the Software is furnished to do
65 * so, subject to the following conditions:
67 * The above copyright notice and this permission notice shall be included in all
68 * copies or substantial portions of the Software.
70 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
86 #include <gst/mpegts/mpegts.h>
89 #include "tsmuxstream.h"
91 #define GST_CAT_DEFAULT gst_base_ts_mux_debug
93 /* Maximum total data length for a PAT section is 1024 bytes, minus an
94 * 8 byte header, then the length of each program entry is 32 bits,
95 * then finally a 32 bit CRC. Thus the maximum number of programs in this mux
96 * is (1024 - 8 - 4) / 4 = 253 because it only supports single section PATs */
97 #define TSMUX_MAX_PROGRAMS 253
99 #define TSMUX_SECTION_HDR_SIZE 8
101 #define TSMUX_DEFAULT_NETWORK_ID 0x0001
102 #define TSMUX_DEFAULT_TS_ID 0x0001
104 /* HACK: We use a fixed buffering offset for the PCR at the moment -
105 * this is the amount 'in advance' of the stream that the PCR sits.
107 #define TSMUX_PCR_OFFSET (TSMUX_CLOCK_FREQ / 8)
109 /* Base for all written PCR and DTS/PTS,
110 * so we have some slack to go backwards */
111 #define CLOCK_BASE (TSMUX_CLOCK_FREQ * 10 * 360)
113 static gboolean tsmux_write_pat (TsMux * mux);
114 static gboolean tsmux_write_pmt (TsMux * mux, TsMuxProgram * program);
115 static gboolean tsmux_write_scte_null (TsMux * mux, TsMuxProgram * program);
117 tsmux_section_free (TsMuxSection * section)
119 gst_mpegts_section_unref (section->section);
120 g_slice_free (TsMuxSection, section);
126 * Create a new muxer session.
128 * Returns: A new #TsMux object.
135 mux = g_slice_new0 (TsMux);
137 mux->transport_id = TSMUX_DEFAULT_TS_ID;
139 mux->next_pgm_no = TSMUX_START_PROGRAM_ID;
140 mux->next_pmt_pid = TSMUX_START_PMT_PID;
141 mux->next_stream_pid = TSMUX_START_ES_PID;
143 mux->pat_changed = TRUE;
144 mux->next_pat_pcr = -1;
145 mux->pat_interval = TSMUX_DEFAULT_PAT_INTERVAL;
147 mux->si_changed = TRUE;
148 mux->si_interval = TSMUX_DEFAULT_SI_INTERVAL;
150 mux->pcr_interval = TSMUX_DEFAULT_PCR_INTERVAL;
152 mux->next_si_pcr = -1;
154 mux->si_sections = g_hash_table_new_full (g_direct_hash, g_direct_equal,
155 NULL, (GDestroyNotify) tsmux_section_free);
157 mux->new_stream_func = (TsMuxNewStreamFunc) tsmux_stream_new;
158 mux->new_stream_data = NULL;
164 * tsmux_set_write_func:
166 * @func: a user callback function
167 * @user_data: user data passed to @func
169 * Set the callback function and user data to be called when @mux has output to
170 * produce. @user_data will be passed as user data in @func.
173 tsmux_set_write_func (TsMux * mux, TsMuxWriteFunc func, void *user_data)
175 g_return_if_fail (mux != NULL);
177 mux->write_func = func;
178 mux->write_func_data = user_data;
182 * tsmux_set_alloc_func:
184 * @func: a user callback function
185 * @user_data: user data passed to @func
187 * Set the callback function and user data to be called when @mux needs
188 * a new buffer to write a packet into.
189 * @user_data will be passed as user data in @func.
192 tsmux_set_alloc_func (TsMux * mux, TsMuxAllocFunc func, void *user_data)
194 g_return_if_fail (mux != NULL);
196 mux->alloc_func = func;
197 mux->alloc_func_data = user_data;
201 * tsmux_set_new_stream_func:
203 * @func: a user callback function
204 * @user_data: user data passed to @func
206 * Set the callback function and user data to be called when @mux needs
207 * to create a new stream.
208 * @user_data will be passed as user data in @func.
211 tsmux_set_new_stream_func (TsMux * mux, TsMuxNewStreamFunc func,
214 g_return_if_fail (mux != NULL);
216 mux->new_stream_func = func;
217 mux->new_stream_data = user_data;
221 * tsmux_set_pat_interval:
223 * @freq: a new PAT interval
225 * Set the interval (in cycles of the 90kHz clock) for writing out the PAT table.
227 * Many transport stream clients might have problems if the PAT table is not
228 * inserted in the stream at regular intervals, especially when initially trying
229 * to figure out the contents of the stream.
232 tsmux_set_pat_interval (TsMux * mux, guint freq)
234 g_return_if_fail (mux != NULL);
236 mux->pat_interval = freq;
240 * tsmux_set_pcr_interval:
242 * @freq: a new PCR interval
244 * Set the interval (in cycles of the 90kHz clock) for writing the PCR.
247 tsmux_set_pcr_interval (TsMux * mux, guint freq)
249 g_return_if_fail (mux != NULL);
251 mux->pcr_interval = freq;
255 * tsmux_get_pat_interval:
258 * Get the configured PAT interval. See also tsmux_set_pat_interval().
260 * Returns: the configured PAT interval
263 tsmux_get_pat_interval (TsMux * mux)
265 g_return_val_if_fail (mux != NULL, 0);
267 return mux->pat_interval;
274 * Resends the PAT before the next stream packet.
277 tsmux_resend_pat (TsMux * mux)
279 g_return_if_fail (mux != NULL);
281 mux->next_pat_pcr = -1;
285 * tsmux_set_si_interval:
287 * @freq: a new SI table interval
289 * Set the interval (in cycles of the 90kHz clock) for writing out the SI tables.
293 tsmux_set_si_interval (TsMux * mux, guint freq)
295 g_return_if_fail (mux != NULL);
297 mux->si_interval = freq;
301 * tsmux_get_si_interval:
304 * Get the configured SI table interval. See also tsmux_set_si_interval().
306 * Returns: the configured SI interval
309 tsmux_get_si_interval (TsMux * mux)
311 g_return_val_if_fail (mux != NULL, 0);
313 return mux->si_interval;
320 * Resends the SI tables before the next stream packet.
324 tsmux_resend_si (TsMux * mux)
326 g_return_if_fail (mux != NULL);
328 mux->next_si_pcr = -1;
332 * tsmux_add_mpegts_si_section:
334 * @section: (transfer full): a #GstMpegtsSection to add
336 * Add a Service Information #GstMpegtsSection to the stream
338 * Returns: %TRUE on success, %FALSE otherwise
341 tsmux_add_mpegts_si_section (TsMux * mux, GstMpegtsSection * section)
343 TsMuxSection *tsmux_section;
345 g_return_val_if_fail (mux != NULL, FALSE);
346 g_return_val_if_fail (section != NULL, FALSE);
347 g_return_val_if_fail (mux->si_sections != NULL, FALSE);
349 tsmux_section = g_slice_new0 (TsMuxSection);
351 GST_DEBUG ("Adding mpegts section with type %d to mux",
352 section->section_type);
354 tsmux_section->section = section;
355 tsmux_section->pi.pid = section->pid;
357 g_hash_table_insert (mux->si_sections,
358 GINT_TO_POINTER (section->section_type), tsmux_section);
360 mux->si_changed = TRUE;
370 * Free all resources associated with @mux. After calling this function @mux can
371 * not be used anymore.
374 tsmux_free (TsMux * mux)
378 g_return_if_fail (mux != NULL);
380 /* Free PAT section */
381 if (mux->pat.section)
382 gst_mpegts_section_unref (mux->pat.section);
384 /* Free all programs */
385 for (cur = mux->programs; cur; cur = cur->next) {
386 TsMuxProgram *program = (TsMuxProgram *) cur->data;
388 tsmux_program_free (program);
390 g_list_free (mux->programs);
392 /* Free all streams */
393 for (cur = mux->streams; cur; cur = cur->next) {
394 TsMuxStream *stream = (TsMuxStream *) cur->data;
396 tsmux_stream_free (stream);
398 g_list_free (mux->streams);
400 /* Free SI table sections */
401 g_hash_table_unref (mux->si_sections);
403 g_slice_free (TsMux, mux);
407 tsmux_program_compare (TsMuxProgram * program, gint * needle)
409 return (program->pgm_number - *needle);
416 * Create a new program in the missing session @mux.
418 * Returns: a new #TsMuxProgram or %NULL when the maximum number of programs has
422 tsmux_program_new (TsMux * mux, gint prog_id)
424 TsMuxProgram *program;
426 g_return_val_if_fail (mux != NULL, NULL);
428 /* Ensure we have room for another program */
429 if (mux->nb_programs == TSMUX_MAX_PROGRAMS)
432 program = g_slice_new0 (TsMuxProgram);
434 program->pmt_changed = TRUE;
435 program->pmt_interval = TSMUX_DEFAULT_PMT_INTERVAL;
437 program->next_pmt_pcr = -1;
440 program->pgm_number = mux->next_pgm_no++;
441 while (g_list_find_custom (mux->programs, &program->pgm_number,
442 (GCompareFunc) tsmux_program_compare) != NULL) {
443 program->pgm_number = mux->next_pgm_no++;
446 program->pgm_number = prog_id;
447 while (g_list_find_custom (mux->programs, &program->pgm_number,
448 (GCompareFunc) tsmux_program_compare) != NULL) {
449 program->pgm_number++;
453 program->pmt_pid = mux->next_pmt_pid++;
454 program->pcr_stream = NULL;
456 /* SCTE35 is disabled by default */
457 program->scte35_pid = 0;
458 program->scte35_null_interval = TSMUX_DEFAULT_SCTE_35_NULL_INTERVAL;
459 program->next_scte35_pcr = -1;
461 program->streams = g_array_sized_new (FALSE, TRUE, sizeof (TsMuxStream *), 1);
463 mux->programs = g_list_prepend (mux->programs, program);
465 mux->pat_changed = TRUE;
471 * tsmux_set_pmt_interval:
472 * @program: a #TsMuxProgram
473 * @freq: a new PMT interval
475 * Set the interval (in cycles of the 90kHz clock) for writing out the PMT table.
477 * Many transport stream clients might have problems if the PMT table is not
478 * inserted in the stream at regular intervals, especially when initially trying
479 * to figure out the contents of the stream.
482 tsmux_set_pmt_interval (TsMuxProgram * program, guint freq)
484 g_return_if_fail (program != NULL);
486 program->pmt_interval = freq;
490 * tsmux_get_pmt_interval:
491 * @program: a #TsMuxProgram
493 * Get the configured PMT interval. See also tsmux_set_pmt_interval().
495 * Returns: the configured PMT interval
498 tsmux_get_pmt_interval (TsMuxProgram * program)
500 g_return_val_if_fail (program != NULL, 0);
502 return program->pmt_interval;
506 * tsmux_program_set_scte35_interval:
507 * @program: a #TsMuxProgram
508 * @freq: a new SCTE-35 NULL interval
510 * Set the interval (in cycles of the 90kHz clock) for sending out the SCTE-35
511 * NULL command. This is only effective is the SCTE-35 PID is not 0.
514 tsmux_program_set_scte35_interval (TsMuxProgram * program, guint interval)
516 g_return_if_fail (program != NULL);
518 program->scte35_null_interval = interval;
523 * @program: a #TsMuxProgram
525 * Resends the PMT before the next stream packet.
528 tsmux_resend_pmt (TsMuxProgram * program)
530 g_return_if_fail (program != NULL);
532 program->next_pmt_pcr = -1;
536 * tsmux_program_set_scte35_pid:
537 * @program: a #TsMuxProgram
538 * @pid: The pid to use, or 0 to deactivate usage.
540 * Set the @pid to use for sending SCTE-35 packets on the given
543 * This needs to be called as early as possible if SCTE-35 sections
544 * are even going to be used with the given @program so that the PMT
545 * can be properly configured.
548 tsmux_program_set_scte35_pid (TsMuxProgram * program, guint16 pid)
550 TsMuxSection *section;
551 GstMpegtsSCTESIT *sit;
552 g_return_if_fail (program != NULL);
554 program->scte35_pid = pid;
555 /* Create/Update the section */
556 if (program->scte35_null_section) {
557 tsmux_section_free (program->scte35_null_section);
558 program->scte35_null_section = NULL;
561 program->scte35_null_section = section = g_slice_new0 (TsMuxSection);
562 section->pi.pid = pid;
563 sit = gst_mpegts_scte_null_new ();
564 section->section = gst_mpegts_section_from_scte_sit (sit, pid);
569 * tsmux_program_get_scte35_pid:
570 * @program: a #TsMuxProgram
572 * Get the PID configured for sending SCTE-35 packets.
574 * Returns: the configured SCTE-35 PID, or 0 if not active.
577 tsmux_program_get_scte35_pid (TsMuxProgram * program)
579 g_return_val_if_fail (program != NULL, 0);
581 return program->scte35_pid;
585 * tsmux_program_add_stream:
586 * @program: a #TsMuxProgram
587 * @stream: a #TsMuxStream
589 * Add @stream to @program.
592 tsmux_program_add_stream (TsMuxProgram * program, TsMuxStream * stream)
594 g_return_if_fail (program != NULL);
595 g_return_if_fail (stream != NULL);
597 g_array_append_val (program->streams, stream);
598 program->pmt_changed = TRUE;
602 * tsmux_program_set_pcr_stream:
603 * @program: a #TsMuxProgram
604 * @stream: a #TsMuxStream
606 * Set @stream as the PCR stream for @program, overwriting the previously
607 * configured PCR stream. When @stream is NULL, program will have no PCR stream
611 tsmux_program_set_pcr_stream (TsMuxProgram * program, TsMuxStream * stream)
613 g_return_if_fail (program != NULL);
615 if (program->pcr_stream == stream)
618 if (program->pcr_stream != NULL)
619 tsmux_stream_pcr_unref (program->pcr_stream);
621 tsmux_stream_pcr_ref (stream);
622 program->pcr_stream = stream;
624 program->pmt_changed = TRUE;
631 * Get a new free PID.
633 * Returns: a new free PID.
636 tsmux_get_new_pid (TsMux * mux)
638 g_return_val_if_fail (mux != NULL, -1);
640 /* make sure this PID is free
641 * (and not taken by a specific earlier request) */
643 mux->next_stream_pid++;
644 } while (tsmux_find_stream (mux, mux->next_stream_pid));
646 return mux->next_stream_pid;
650 * tsmux_create_stream:
652 * @stream_type: the stream type
653 * @pid: the PID of the new stream.
655 * Create a new stream of @stream_type in the muxer session @mux.
657 * When @pid is set to #TSMUX_PID_AUTO, a new free PID will automatically
658 * be allocated for the new stream.
660 * Returns: a new #TsMuxStream.
663 tsmux_create_stream (TsMux * mux, guint stream_type, guint16 pid,
669 g_return_val_if_fail (mux != NULL, NULL);
670 g_return_val_if_fail (mux->new_stream_func != NULL, NULL);
672 if (pid == TSMUX_PID_AUTO) {
673 new_pid = tsmux_get_new_pid (mux);
675 new_pid = pid & 0x1FFF;
678 /* Ensure we're not creating a PID collision */
679 if (tsmux_find_stream (mux, new_pid))
682 stream = mux->new_stream_func (new_pid, stream_type, mux->new_stream_data);
684 mux->streams = g_list_prepend (mux->streams, stream);
688 g_strlcat (stream->language, language, 3 * sizeof (gchar));
690 g_strlcat (stream->language, "eng", 3 * sizeof (gchar));
698 * @pid: the PID to find.
700 * Find the stream associated with PID.
702 * Returns: a #TsMuxStream with @pid or NULL when the stream was not found.
705 tsmux_find_stream (TsMux * mux, guint16 pid)
707 TsMuxStream *found = NULL;
710 g_return_val_if_fail (mux != NULL, NULL);
712 for (cur = mux->streams; cur; cur = cur->next) {
713 TsMuxStream *stream = (TsMuxStream *) cur->data;
715 if (tsmux_stream_get_pid (stream) == pid) {
724 tsmux_get_buffer (TsMux * mux, GstBuffer ** buf)
726 g_return_val_if_fail (buf, FALSE);
728 if (G_UNLIKELY (!mux->alloc_func))
731 mux->alloc_func (buf, mux->alloc_func_data);
736 g_assert (gst_buffer_get_size (*buf) == TSMUX_PACKET_LENGTH);
741 tsmux_packet_out (TsMux * mux, GstBuffer * buf, gint64 pcr)
743 if (G_UNLIKELY (mux->write_func == NULL)) {
745 gst_buffer_unref (buf);
750 GST_BUFFER_PTS (buf) =
751 gst_util_uint64_scale (mux->n_bytes * 8, GST_SECOND, mux->bitrate);
753 mux->n_bytes += gst_buffer_get_size (buf);
755 return mux->write_func (buf, mux->write_func_data, pcr);
759 * adaptation_field() {
760 * adaptation_field_length 8 uimsbf
761 * if(adaptation_field_length >0) {
762 * discontinuity_indicator 1 bslbf
763 * random_access_indicator 1 bslbf
764 * elementary_stream_priority_indicator 1 bslbf
767 * splicing_point_flag 1 bslbf
768 * transport_private_data_flag 1 bslbf
769 * adaptation_field_extension_flag 1 bslbf
770 * if(PCR_flag == '1') {
771 * program_clock_reference_base 33 uimsbf
773 * program_clock_reference_extension 9 uimsbf
775 * if(OPCR_flag == '1') {
776 * original_program_clock_reference_base 33 uimsbf
778 * original_program_clock_reference_extension 9 uimsbf
780 * if (splicing_point_flag == '1') {
781 * splice_countdown 8 tcimsbf
783 * if(transport_private_data_flag == '1') {
784 * transport_private_data_length 8 uimsbf
785 * for (i=0; i<transport_private_data_length;i++){
786 * private_data_byte 8 bslbf
789 * if (adaptation_field_extension_flag == '1' ) {
790 * adaptation_field_extension_length 8 uimsbf
792 * piecewise_rate_flag 1 bslbf
793 * seamless_splice_flag 1 bslbf
795 * if (ltw_flag == '1') {
796 * ltw_valid_flag 1 bslbf
797 * ltw_offset 15 uimsbf
799 * if (piecewise_rate_flag == '1') {
801 * piecewise_rate 22 uimsbf
803 * if (seamless_splice_flag == '1'){
804 * splice_type 4 bslbf
805 * DTS_next_AU[32..30] 3 bslbf
807 * DTS_next_AU[29..15] 15 bslbf
809 * DTS_next_AU[14..0] 15 bslbf
812 * for ( i=0;i<N;i++) {
817 * stuffing_byte 8 bslbf
823 tsmux_write_adaptation_field (guint8 * buf,
824 TsMuxPacketInfo * pi, guint8 min_length, guint8 * written)
829 g_assert (min_length <= TSMUX_PAYLOAD_LENGTH);
831 /* Write out all the fields from the packet info only if the
832 * user set the flag to request the adaptation field - if the flag
833 * isn't set, we're just supposed to write stuffing bytes */
834 if (pi->flags & TSMUX_PACKET_FLAG_ADAPTATION) {
835 TS_DEBUG ("writing adaptation fields");
836 if (pi->flags & TSMUX_PACKET_FLAG_DISCONT)
838 if (pi->flags & TSMUX_PACKET_FLAG_RANDOM_ACCESS)
840 if (pi->flags & TSMUX_PACKET_FLAG_PRIORITY)
842 if (pi->flags & TSMUX_PACKET_FLAG_WRITE_PCR) {
846 pcr_base = (pi->pcr / 300);
847 pcr_ext = (pi->pcr % 300);
850 TS_DEBUG ("Writing PCR %" G_GUINT64_FORMAT " + ext %u", pcr_base,
852 buf[pos++] = (pcr_base >> 25) & 0xff;
853 buf[pos++] = (pcr_base >> 17) & 0xff;
854 buf[pos++] = (pcr_base >> 9) & 0xff;
855 buf[pos++] = (pcr_base >> 1) & 0xff;
856 buf[pos++] = ((pcr_base << 7) & 0x80) | 0x7e | ((pcr_ext >> 8) & 0x01); /* set 6 reserve bits to 1 */
857 buf[pos++] = (pcr_ext) & 0xff;
859 if (pi->flags & TSMUX_PACKET_FLAG_WRITE_OPCR) {
863 opcr_base = (pi->opcr / 300);
864 opcr_ext = (pi->opcr % 300);
867 TS_DEBUG ("Writing OPCR");
868 buf[pos++] = (opcr_base >> 25) & 0xff;
869 buf[pos++] = (opcr_base >> 17) & 0xff;
870 buf[pos++] = (opcr_base >> 9) & 0xff;
871 buf[pos++] = (opcr_base >> 1) & 0xff;
872 buf[pos++] = ((opcr_base << 7) & 0x80) | 0x7e | ((opcr_ext >> 8) & 0x01); /* set 6 reserve bits to 1 */
873 buf[pos++] = (opcr_ext) & 0xff;
875 if (pi->flags & TSMUX_PACKET_FLAG_WRITE_SPLICE) {
877 buf[pos++] = pi->splice_countdown;
879 if (pi->private_data_len > 0) {
881 /* Private data to write, ensure we have enough room */
882 if ((1 + pi->private_data_len) > (TSMUX_PAYLOAD_LENGTH - pos))
884 buf[pos++] = pi->private_data_len;
885 memcpy (&(buf[pos]), pi->private_data, pi->private_data_len);
886 pos += pi->private_data_len;
887 TS_DEBUG ("%u bytes of private data", pi->private_data_len);
889 if (pi->flags & TSMUX_PACKET_FLAG_WRITE_ADAPT_EXT) {
891 TS_DEBUG ("FIXME: write Adaptation extension");
892 /* Write an empty extension for now */
894 buf[pos++] = 0x1f; /* lower 5 bits are reserved, and should be all 1 */
897 /* Write the flags at the start */
900 /* Stuffing bytes if needed */
901 while (pos < min_length)
904 /* Write the adaptation field length, which doesn't include its own byte */
914 tsmux_write_ts_header (TsMux * mux, guint8 * buf, TsMuxPacketInfo * pi,
915 guint * payload_len_out, guint * payload_offset_out, guint stream_avail)
918 guint8 adaptation_flag = 0;
919 guint8 adapt_min_length = 0;
920 guint8 adapt_len = 0;
922 gboolean write_adapt = FALSE;
925 buf[0] = TSMUX_SYNC_BYTE;
927 TS_DEBUG ("PID 0x%04x, counter = 0x%01x, %u bytes avail", pi->pid,
928 mux->pid_packet_counts[pi->pid] & 0x0f, stream_avail);
931 * transport_error_indicator
932 * payload_unit_start_indicator
933 * transport_priority: (00)
937 if (pi->packet_start_unit_indicator) {
938 tsmux_put16 (&tmp, 0x4000 | pi->pid);
940 tsmux_put16 (&tmp, pi->pid);
942 /* 2 bits: scrambling_control (NOT SUPPORTED) (00)
943 * 2 bits: adaptation field control (1x has_adaptation_field | x1 has_payload)
944 * 4 bits: continuity counter (xxxx)
947 if (pi->flags & TSMUX_PACKET_FLAG_ADAPTATION) {
951 if (stream_avail < TSMUX_PAYLOAD_LENGTH) {
952 /* Need an adaptation field regardless for stuffing */
953 adapt_min_length = TSMUX_PAYLOAD_LENGTH - stream_avail;
960 /* Flag the adaptation field presence */
961 adaptation_flag |= 0x20;
962 res = tsmux_write_adaptation_field (buf + TSMUX_HEADER_LENGTH,
963 pi, adapt_min_length, &adapt_len);
964 if (G_UNLIKELY (res == FALSE))
967 /* Should have written at least the number of bytes we requested */
968 g_assert (adapt_len >= adapt_min_length);
971 /* The amount of packet data we wrote is the remaining space after
972 * the adaptation field */
973 *payload_len_out = payload_len = TSMUX_PAYLOAD_LENGTH - adapt_len;
974 *payload_offset_out = TSMUX_HEADER_LENGTH + adapt_len;
976 /* Now if we are going to write out some payload, flag that fact */
977 if (payload_len > 0 && stream_avail > 0) {
978 /* Flag the presence of a payload */
979 adaptation_flag |= 0x10;
981 /* We must have enough data to fill the payload, or some calculation
983 g_assert (payload_len <= stream_avail);
985 /* Packet with payload, increment the continuity counter */
986 mux->pid_packet_counts[pi->pid]++;
989 adaptation_flag |= mux->pid_packet_counts[pi->pid] & 0x0f;
991 /* Write the byte of transport_scrambling_control, adaptation_field_control
992 * + continuity counter out */
993 buf[3] = adaptation_flag;
997 TS_DEBUG ("Adaptation field of size >= %d + %d bytes payload",
998 adapt_len, payload_len);
1000 TS_DEBUG ("Payload of %d bytes only", payload_len);
1006 /* The unused_arg is needed for g_hash_table_foreach() */
1008 tsmux_section_write_packet (gpointer unused_arg,
1009 TsMuxSection * section, TsMux * mux)
1011 GstBuffer *section_buffer;
1012 GstBuffer *packet_buffer = NULL;
1016 gsize data_size = 0;
1017 gsize payload_written;
1018 guint len = 0, offset = 0, payload_len = 0;
1019 guint extra_alloc_bytes = 0;
1021 g_return_val_if_fail (section != NULL, FALSE);
1022 g_return_val_if_fail (mux != NULL, FALSE);
1024 /* Mark the start of new PES unit */
1025 section->pi.packet_start_unit_indicator = TRUE;
1027 data = gst_mpegts_section_packetize (section->section, &data_size);
1030 TS_DEBUG ("Could not packetize section");
1034 /* Mark payload data size */
1035 section->pi.stream_avail = data_size;
1036 payload_written = 0;
1038 /* Wrap section data in a buffer without free function.
1039 The data will be freed when the GstMpegtsSection is destroyed. */
1040 section_buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
1041 data, data_size, 0, data_size, NULL, NULL);
1043 TS_DEBUG ("Section buffer with size %" G_GSIZE_FORMAT " created",
1044 gst_buffer_get_size (section_buffer));
1046 while (section->pi.stream_avail > 0) {
1048 packet = g_malloc (TSMUX_PACKET_LENGTH);
1050 if (section->pi.packet_start_unit_indicator) {
1051 /* Wee need room for a pointer byte */
1052 section->pi.stream_avail++;
1054 if (!tsmux_write_ts_header (mux, packet, §ion->pi, &len, &offset,
1055 section->pi.stream_avail))
1058 /* Write the pointer byte */
1059 packet[offset++] = 0x00;
1060 payload_len = len - 1;
1063 if (!tsmux_write_ts_header (mux, packet, §ion->pi, &len, &offset,
1064 section->pi.stream_avail))
1069 /* Wrap the TS header and adaption field in a GstMemory */
1070 mem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
1071 packet, TSMUX_PACKET_LENGTH, 0, offset, packet, g_free);
1073 TS_DEBUG ("Creating packet buffer at offset "
1074 "%" G_GSIZE_FORMAT " with length %u", payload_written, payload_len);
1076 /* If in M2TS mode, we will need to resize to 4 bytes after the end
1077 of the buffer. For performance reasons, we will now try to include
1078 4 extra bytes from the source buffer, then resize down, to avoid
1079 having an extra 4 byte GstMemory appended. If the source buffer
1080 does not have enough data for this, a new GstMemory will be used */
1081 if (gst_buffer_get_size (section_buffer) - (payload_written +
1082 payload_len) >= 4) {
1084 extra_alloc_bytes = 4;
1086 packet_buffer = gst_buffer_copy_region (section_buffer, GST_BUFFER_COPY_ALL,
1087 payload_written, payload_len + extra_alloc_bytes);
1089 /* Prepend the header to the section data */
1090 gst_buffer_prepend_memory (packet_buffer, mem);
1092 /* add an extra 4 bytes if it could not be reserved already */
1093 if (extra_alloc_bytes == 4) {
1094 /* we allocated those already, resize */
1095 gst_buffer_set_size (packet_buffer,
1096 gst_buffer_get_size (packet_buffer) - extra_alloc_bytes);
1098 void *ptr = g_malloc (4);
1100 gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY, ptr, 4, 0, 0, ptr,
1102 gst_buffer_append_memory (packet_buffer, extra);
1105 TS_DEBUG ("Writing %d bytes to section. %d bytes remaining",
1106 len, section->pi.stream_avail - len);
1108 /* Push the packet without PCR */
1109 if (G_UNLIKELY (!tsmux_packet_out (mux, packet_buffer, -1))) {
1110 /* Buffer given away */
1111 packet_buffer = NULL;
1115 packet_buffer = NULL;
1116 section->pi.stream_avail -= len;
1117 payload_written += payload_len;
1118 section->pi.packet_start_unit_indicator = FALSE;
1121 gst_buffer_unref (section_buffer);
1128 gst_buffer_unref (section_buffer);
1133 * tsmux_send_section:
1135 * @section: (transfer full): a #GstMpegtsSection to add
1137 * Send a @section immediately on the stream.
1139 * Returns: %TRUE on success, %FALSE otherwise
1142 tsmux_send_section (TsMux * mux, GstMpegtsSection * section)
1145 TsMuxSection tsmux_section;
1147 g_return_val_if_fail (mux != NULL, FALSE);
1148 g_return_val_if_fail (section != NULL, FALSE);
1150 memset (&tsmux_section, 0, sizeof (tsmux_section));
1152 GST_DEBUG ("Sending mpegts section with type %d to mux",
1153 section->section_type);
1155 tsmux_section.section = section;
1156 tsmux_section.pi.pid = section->pid;
1158 ret = tsmux_section_write_packet (NULL, &tsmux_section, mux);
1159 gst_mpegts_section_unref (section);
1165 tsmux_write_si (TsMux * mux)
1167 g_hash_table_foreach (mux->si_sections,
1168 (GHFunc) tsmux_section_write_packet, mux);
1170 mux->si_changed = FALSE;
1177 tsmux_write_null_ts_header (guint8 * buf)
1179 *buf++ = TSMUX_SYNC_BYTE;
1186 get_current_pcr (TsMux * mux, gint64 cur_ts)
1189 return (CLOCK_BASE - TSMUX_PCR_OFFSET) * 300 +
1190 gst_util_uint64_scale (mux->n_bytes * 8, TSMUX_SYS_CLOCK_FREQ,
1192 else if (cur_ts != G_MININT64)
1194 TSMUX_PCR_OFFSET) * (TSMUX_SYS_CLOCK_FREQ / TSMUX_CLOCK_FREQ);
1200 write_new_pcr (TsMux * mux, TsMuxStream * stream, gint64 cur_pcr)
1202 if (stream->next_pcr == -1 || cur_pcr > stream->next_pcr) {
1204 TSMUX_PACKET_FLAG_ADAPTATION | TSMUX_PACKET_FLAG_WRITE_PCR;
1205 stream->pi.pcr = cur_pcr;
1207 if (stream->next_pcr == -1)
1208 stream->next_pcr = cur_pcr + mux->pcr_interval * 300;
1210 stream->next_pcr += mux->pcr_interval * 300;
1219 rewrite_si (TsMux * mux, gint64 cur_ts)
1226 cur_pcr = get_current_pcr (mux, cur_ts);
1228 /* check if we need to rewrite pat */
1229 if (mux->next_pat_pcr == -1 || mux->pat_changed)
1231 else if (cur_pcr > mux->next_pat_pcr)
1237 if (mux->next_pat_pcr == -1)
1238 mux->next_pat_pcr = cur_pcr + mux->pat_interval * 300;
1240 mux->next_pat_pcr += mux->pat_interval * 300;
1242 if (!tsmux_write_pat (mux))
1245 cur_pcr = get_current_pcr (mux, cur_ts);
1248 /* check if we need to rewrite sit */
1249 if (mux->next_si_pcr == -1 || mux->si_changed)
1251 else if (cur_pcr > mux->next_si_pcr)
1257 if (mux->next_si_pcr == -1)
1258 mux->next_si_pcr = cur_pcr + mux->si_interval * 300;
1260 mux->next_si_pcr += mux->si_interval * 300;
1262 if (!tsmux_write_si (mux))
1265 cur_pcr = get_current_pcr (mux, cur_ts);
1268 /* check if we need to rewrite any of the current pmts */
1269 for (cur = mux->programs; cur; cur = cur->next) {
1270 TsMuxProgram *program = (TsMuxProgram *) cur->data;
1273 if (program->next_pmt_pcr == -1 || program->pmt_changed)
1275 else if (cur_pcr > program->next_pmt_pcr)
1281 if (program->next_pmt_pcr == -1)
1282 program->next_pmt_pcr = cur_pcr + program->pmt_interval * 300;
1284 program->next_pmt_pcr += program->pmt_interval * 300;
1286 if (!tsmux_write_pmt (mux, program))
1289 cur_pcr = get_current_pcr (mux, cur_ts);
1292 if (program->scte35_pid != 0) {
1293 gboolean write_scte_null = FALSE;
1294 if (program->next_scte35_pcr == -1)
1295 write_scte_null = TRUE;
1296 else if (cur_pcr > program->next_scte35_pcr)
1297 write_scte_null = TRUE;
1299 if (write_scte_null) {
1300 GST_DEBUG ("next scte35 pcr %" G_GINT64_FORMAT,
1301 program->next_scte35_pcr);
1302 if (program->next_scte35_pcr == -1)
1303 program->next_scte35_pcr =
1304 cur_pcr + program->scte35_null_interval * 300;
1306 program->next_scte35_pcr += program->scte35_null_interval * 300;
1307 GST_DEBUG ("next scte35 NOW pcr %" G_GINT64_FORMAT,
1308 program->next_scte35_pcr);
1310 if (!tsmux_write_scte_null (mux, program))
1313 cur_pcr = get_current_pcr (mux, cur_ts);
1322 pad_stream (TsMux * mux, TsMuxStream * stream, gint64 cur_ts)
1325 GstBuffer *buf = NULL;
1327 gboolean ret = TRUE;
1333 if (GST_CLOCK_STIME_IS_VALID (cur_ts)) {
1334 GstClockTimeDiff diff;
1336 if (!GST_CLOCK_STIME_IS_VALID (stream->first_ts))
1337 stream->first_ts = cur_ts;
1339 diff = GST_CLOCK_DIFF (stream->first_ts, cur_ts);
1343 gst_util_uint64_scale (mux->n_bytes * 8, TSMUX_CLOCK_FREQ, diff);
1345 GST_LOG ("Transport stream bitrate: %" G_GUINT64_FORMAT, bitrate);
1347 if (bitrate < mux->bitrate) {
1349 guint payload_len, payload_offs;
1351 GST_LOG ("Padding transport stream");
1353 if (!rewrite_si (mux, cur_ts)) {
1358 if (!tsmux_get_buffer (mux, &buf)) {
1363 gst_buffer_map (buf, &map, GST_MAP_READ);
1366 write_new_pcr (mux, stream, get_current_pcr (mux,
1368 tsmux_write_ts_header (mux, map.data, &stream->pi, &payload_len,
1371 tsmux_write_null_ts_header (map.data);
1373 gst_buffer_unmap (buf, &map);
1375 stream->pi.flags &= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
1377 if (!(ret = tsmux_packet_out (mux, buf, new_pcr)))
1386 } while (bitrate < mux->bitrate);
1393 * tsmux_write_stream_packet:
1395 * @stream: a #TsMuxStream
1397 * Write a packet of @stream.
1399 * Returns: TRUE if the packet could be written.
1402 tsmux_write_stream_packet (TsMux * mux, TsMuxStream * stream)
1404 guint payload_len, payload_offs;
1405 TsMuxPacketInfo *pi = &stream->pi;
1407 gint64 new_pcr = -1;
1408 GstBuffer *buf = NULL;
1411 g_return_val_if_fail (mux != NULL, FALSE);
1412 g_return_val_if_fail (stream != NULL, FALSE);
1414 if (tsmux_stream_is_pcr (stream)) {
1415 gint64 cur_ts = CLOCK_BASE;
1417 if (tsmux_stream_get_dts (stream) != G_MININT64)
1418 cur_ts += tsmux_stream_get_dts (stream);
1420 cur_ts += tsmux_stream_get_pts (stream);
1422 if (!rewrite_si (mux, cur_ts))
1425 if (!pad_stream (mux, stream, cur_ts))
1428 new_pcr = write_new_pcr (mux, stream, get_current_pcr (mux, cur_ts));
1431 pi->packet_start_unit_indicator = tsmux_stream_at_pes_start (stream);
1432 if (pi->packet_start_unit_indicator) {
1433 tsmux_stream_initialize_pes_packet (stream);
1434 if (stream->dts != G_MININT64)
1435 stream->dts += CLOCK_BASE;
1436 if (stream->pts != G_MININT64)
1437 stream->pts += CLOCK_BASE;
1439 pi->stream_avail = tsmux_stream_bytes_avail (stream);
1442 if (!tsmux_get_buffer (mux, &buf))
1445 gst_buffer_map (buf, &map, GST_MAP_READ);
1447 if (!tsmux_write_ts_header (mux, map.data, pi, &payload_len, &payload_offs,
1452 if (!tsmux_stream_get_data (stream, map.data + payload_offs, payload_len))
1455 gst_buffer_unmap (buf, &map);
1457 GST_DEBUG ("Writing PES of size %d", (int) gst_buffer_get_size (buf));
1458 res = tsmux_packet_out (mux, buf, new_pcr);
1460 /* Reset all dynamic flags */
1461 stream->pi.flags &= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
1469 gst_buffer_unmap (buf, &map);
1470 gst_buffer_unref (buf);
1477 * tsmux_program_free:
1478 * @program: a #TsMuxProgram
1480 * Free the resources of @program. After this call @program can not be used
1484 tsmux_program_free (TsMuxProgram * program)
1486 g_return_if_fail (program != NULL);
1488 /* Free PMT section */
1489 if (program->pmt.section)
1490 gst_mpegts_section_unref (program->pmt.section);
1491 if (program->scte35_null_section)
1492 tsmux_section_free (program->scte35_null_section);
1494 g_array_free (program->streams, TRUE);
1495 g_slice_free (TsMuxProgram, program);
1499 tsmux_write_pat (TsMux * mux)
1502 if (mux->pat_changed) {
1503 /* program_association_section ()
1504 * for (i = 0; i < N; i++) {
1505 * program_number 16 uimsbf
1507 * network_PID_or_program_map_PID 13 uimbsf
1514 pat = gst_mpegts_pat_new ();
1516 for (cur = mux->programs; cur; cur = cur->next) {
1517 GstMpegtsPatProgram *pat_pgm;
1518 TsMuxProgram *program = (TsMuxProgram *) cur->data;
1520 pat_pgm = gst_mpegts_pat_program_new ();
1521 pat_pgm->program_number = program->pgm_number;
1522 pat_pgm->network_or_program_map_PID = program->pmt_pid;
1524 g_ptr_array_add (pat, pat_pgm);
1527 if (mux->pat.section)
1528 gst_mpegts_section_unref (mux->pat.section);
1530 mux->pat.section = gst_mpegts_section_from_pat (pat, mux->transport_id);
1532 mux->pat.section->version_number = mux->pat_version++;
1534 TS_DEBUG ("PAT has %d programs", mux->nb_programs);
1535 mux->pat_changed = FALSE;
1538 return tsmux_section_write_packet (NULL, &mux->pat, mux);
1542 tsmux_write_pmt (TsMux * mux, TsMuxProgram * program)
1545 if (program->pmt_changed) {
1546 /* program_association_section ()
1550 * program_info_length 12 uimsbf
1551 * for (i = 0; i < N; i++)
1554 * for (i = 0; i < N1; i++) {
1555 * stream_type 8 uimsbf
1557 * elementary_PID 13 uimbsf
1559 * ES_info_length 12 uimbsf
1560 * for (i = 0; i < N1; i++) {
1565 GstMpegtsDescriptor *descriptor;
1568 /* See note about bluray descriptors below */
1569 guint8 desc[] = { 0x0F, 0xFF, 0xFC, 0xFC };
1573 pmt = gst_mpegts_pmt_new ();
1575 if (program->pcr_stream == NULL)
1576 pmt->pcr_pid = 0x1FFF;
1578 pmt->pcr_pid = tsmux_stream_get_pid (program->pcr_stream);
1581 /* FIXME : These two descriptors should not be added in all PMT
1582 * but only in "bluray-compatible" mpeg-ts output. I even have my
1583 * doubt whether the DTCP descriptor is even needed */
1584 descriptor = gst_mpegts_descriptor_from_registration ("HDMV", NULL, 0);
1585 g_ptr_array_add (pmt->descriptors, descriptor);
1587 /* DTCP descriptor, see
1588 * http://www.dtcp.com/documents/dtcp/info-20150204-dtcp-v1-rev%201-71.pdf */
1589 descriptor = gst_mpegts_descriptor_from_custom (0x88, desc, 4);
1590 g_ptr_array_add (pmt->descriptors, descriptor);
1593 /* Will SCTE-35 be potentially used ? */
1594 if (program->scte35_pid != 0) {
1595 descriptor = gst_mpegts_descriptor_from_registration ("CUEI", NULL, 0);
1596 g_ptr_array_add (pmt->descriptors, descriptor);
1599 /* Write out the entries */
1600 for (i = 0; i < program->streams->len; i++) {
1601 GstMpegtsPMTStream *pmt_stream;
1602 TsMuxStream *stream = g_array_index (program->streams, TsMuxStream *, i);
1604 pmt_stream = gst_mpegts_pmt_stream_new ();
1606 /* FIXME: Use API to retrieve this from the stream */
1607 pmt_stream->stream_type = stream->stream_type;
1608 pmt_stream->pid = tsmux_stream_get_pid (stream);
1610 /* Write any ES descriptors needed */
1611 tsmux_stream_get_es_descrs (stream, pmt_stream);
1612 g_ptr_array_add (pmt->streams, pmt_stream);
1615 /* Will SCTE-35 be potentially used ? */
1616 if (program->scte35_pid != 0) {
1617 GstMpegtsPMTStream *pmt_stream = gst_mpegts_pmt_stream_new ();
1618 pmt_stream->stream_type = GST_MPEGTS_STREAM_TYPE_SCTE_SIT;
1619 pmt_stream->pid = program->scte35_pid;
1620 g_ptr_array_add (pmt->streams, pmt_stream);
1623 TS_DEBUG ("PMT for program %d has %d streams",
1624 program->pgm_number, program->streams->len);
1626 pmt->program_number = program->pgm_number;
1628 program->pmt.pi.pid = program->pmt_pid;
1629 program->pmt_changed = FALSE;
1631 if (program->pmt.section)
1632 gst_mpegts_section_unref (program->pmt.section);
1634 program->pmt.section = gst_mpegts_section_from_pmt (pmt, program->pmt_pid);
1635 program->pmt.section->version_number = program->pmt_version++;
1638 return tsmux_section_write_packet (NULL, &program->pmt, mux);
1642 tsmux_write_scte_null (TsMux * mux, TsMuxProgram * program)
1644 /* SCTE-35 NULL section is created when PID is set */
1645 GST_LOG ("Writing SCTE NULL packet");
1646 return tsmux_section_write_packet (NULL, program->scte35_null_section, mux);
1650 tsmux_set_bitrate (TsMux * mux, guint64 bitrate)
1652 mux->bitrate = bitrate;