LCOV - code coverage report
Current view: top level - media_tools - m2ts_mux.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1322 1614 81.9 %
Date: 2021-04-29 23:48:07 Functions: 46 47 97.9 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre , Cyril Concolato, Romain Bouqueau
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2020
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / MPEG2-TS multiplexer sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/mpegts.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/media_tools.h>
      29             : 
      30             : #if !defined(GPAC_DISABLE_MPEG2TS_MUX)
      31             : 
      32             : /* 90khz internal delay between two updates for bitrate compute per stream */
      33             : #define BITRATE_UPDATE_WINDOW   90000
      34             : /* length of adaptation_field_length; */
      35             : #define ADAPTATION_LENGTH_LENGTH 1
      36             : /* discontinuty flag, random access flag ... */
      37             : #define ADAPTATION_FLAGS_LENGTH 1
      38             : /* length of adaptation_extension_field_length; */
      39             : #define ADAPTATION_EXTENSION_LENGTH_LENGTH 1
      40             : /* AF des flags and co... */
      41             : #define ADAPTATION_EXTENSION_FLAGS_LENGTH 1
      42             : /* length of encoded pcr */
      43             : #define PCR_LENGTH 6
      44             : 
      45             : #define GF_LANG_UNKNOWN         GF_4CC('u','n','d',' ')
      46             : 
      47             : /*! DASH segment boundary information - these are internal to the muxer*/
      48             : enum
      49             : {
      50             :         /*! not a segment boundary*/
      51             :         GF_SEG_BOUNDARY_NONE=0,
      52             :         /*! segment start*/
      53             :         GF_SEG_BOUNDARY_START,
      54             :         /*! segment start with forced PMT - triggered by setting \ref struct __m2ts_mux.force_pat, triggers a forced PCR*/
      55             :         GF_SEG_BOUNDARY_FORCE_PMT,
      56             :         /*! segment start with forced PCR*/
      57             :         GF_SEG_BOUNDARY_FORCE_PCR,
      58             : };
      59             : 
      60             : static GFINLINE Bool gf_m2ts_time_less(GF_M2TS_Time *a, GF_M2TS_Time *b) {
      61      149335 :         if (a->sec>b->sec) return GF_FALSE;
      62      145286 :         if (a->sec==b->sec) return (a->nanosec<b->nanosec) ? GF_TRUE : GF_FALSE;
      63             :         return GF_TRUE;
      64             : }
      65             : static GFINLINE Bool gf_m2ts_time_equal(GF_M2TS_Time *a, GF_M2TS_Time *b) {
      66       27437 :         return ((a->sec==b->sec) && (a->nanosec == b->nanosec) );
      67             : }
      68             : static GFINLINE Bool gf_m2ts_time_less_or_equal(GF_M2TS_Time *a, GF_M2TS_Time *b) {
      69      384211 :         if (a->sec>b->sec) return GF_FALSE;
      70      256400 :         if (a->sec==b->sec) return (a->nanosec>b->nanosec) ? GF_FALSE : GF_TRUE;
      71             :         return GF_TRUE;
      72             : }
      73             : 
      74      123757 : static GFINLINE void gf_m2ts_time_inc(GF_M2TS_Time *time, u64 delta_inc_num, u32 delta_inc_den)
      75             : {
      76             :         u64 n_sec;
      77             :         u64 sec;
      78             : 
      79             :         /*couldn't compute bitrate - we need to have more info*/
      80      123757 :         if (!delta_inc_den) return;
      81             : 
      82      148993 :         sec = delta_inc_num / delta_inc_den;
      83             : 
      84      148993 :         if (sec) {
      85       19019 :                 time->sec += (u32) sec;
      86       19019 :                 sec *= delta_inc_den;
      87       19019 :                 delta_inc_num = delta_inc_num % sec;
      88             :         }
      89             :         /*move to nanosec - 0x3B9ACA00 = 1000*1000*1000 */
      90             :         n_sec = delta_inc_num;
      91      148993 :         n_sec *= 0x3B9ACA00;
      92      148993 :         n_sec /= delta_inc_den;
      93      148993 :         time->nanosec += (u32) n_sec;
      94      274166 :         while (time->nanosec >= 0x3B9ACA00) {
      95        1416 :                 time->nanosec -= 0x3B9ACA00;
      96        1416 :                 time->sec ++;
      97             :         }
      98             : }
      99             : 
     100             : static GFINLINE s32 gf_m2ts_time_diff_us(GF_M2TS_Time *a, GF_M2TS_Time *b)
     101             : {
     102         530 :         s32 drift = b->nanosec;
     103        1233 :         drift -= a->nanosec;
     104        1233 :         drift /= 1000;
     105        1233 :         if (a->sec != b->sec) {
     106          16 :                 drift += (b->sec - a->sec) * 1000000;
     107             :         }
     108             :         return drift;
     109             : }
     110             : 
     111             : /************************************
     112             :  * Section-related functions
     113             :  ************************************/
     114          75 : void gf_m2ts_mux_table_update(GF_M2TS_Mux_Stream *stream, u8 table_id, u16 table_id_extension,
     115             :                               u8 *table_payload, u32 table_payload_length,
     116             :                               Bool use_syntax_indicator, Bool private_indicator,
     117             :                               Bool use_checksum)
     118             : {
     119             :         u32 overhead_size;
     120             :         u32 offset;
     121             :         u32 section_number, nb_sections;
     122             :         GF_M2TS_Mux_Table *table, *prev_table;
     123             :         u32 maxSectionLength;
     124             :         GF_M2TS_Mux_Section *section, *prev_sec;
     125             : 
     126             :         /* check if there is already a table with that id */
     127             :         prev_table = NULL;
     128          75 :         table = stream->tables;
     129         150 :         while (table) {
     130           0 :                 if (table->table_id == table_id) {
     131             :                         /* if yes, we need to flush the table and increase the version number */
     132           0 :                         GF_M2TS_Mux_Section *sec = table->section;
     133           0 :                         while (sec) {
     134           0 :                                 GF_M2TS_Mux_Section *sec2 = sec->next;
     135           0 :                                 gf_free(sec->data);
     136           0 :                                 gf_free(sec);
     137             :                                 sec = sec2;
     138             :                         }
     139           0 :                         table->version_number = (table->version_number + 1)%0x1F;
     140           0 :                         break;
     141             :                 }
     142             :                 prev_table = table;
     143           0 :                 table = table->next;
     144             :         }
     145             : 
     146          75 :         if (!table) {
     147             :                 /* if no, the table is created */
     148          75 :                 GF_SAFEALLOC(table, GF_M2TS_Mux_Table);
     149          75 :                 if (!table) {
     150           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: fail to allocate table id %d\n", stream->pid, table_id));
     151             :                         return;
     152             :                 }
     153          75 :                 table->table_id = table_id;
     154          75 :                 if (prev_table) prev_table->next = table;
     155          75 :                 else stream->tables = table;
     156          75 :                 table->version_number = stream->initial_version_number;
     157             :         }
     158             : 
     159          75 :         if (!table_payload_length) return;
     160             : 
     161          75 :         switch (table_id) {
     162             :         case GF_M2TS_TABLE_ID_PMT:
     163             :         case GF_M2TS_TABLE_ID_PAT:
     164             :         case GF_M2TS_TABLE_ID_SDT_ACTUAL:
     165             :         case GF_M2TS_TABLE_ID_SDT_OTHER:
     166             :         case GF_M2TS_TABLE_ID_TDT:
     167             :         case GF_M2TS_TABLE_ID_TOT:
     168             :         case GF_M2TS_TABLE_ID_BAT:
     169             :                 maxSectionLength = 1024;
     170             :                 break;
     171           0 :         case GF_M2TS_TABLE_ID_MPEG4_BIFS:
     172             :         case GF_M2TS_TABLE_ID_MPEG4_OD:
     173             :                 maxSectionLength = 4096;
     174           0 :                 break;
     175           0 :         default:
     176           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Cannot create sections for table id %d\n", stream->pid, table_id));
     177             :                 return;
     178             :         }
     179             : 
     180             :         overhead_size = SECTION_HEADER_LENGTH;
     181          75 :         if (use_syntax_indicator) overhead_size += SECTION_ADDITIONAL_HEADER_LENGTH + CRC_LENGTH;
     182             : 
     183             :         section_number = 0;
     184             :         nb_sections = 1;
     185          75 :         while (nb_sections*(maxSectionLength - overhead_size)<table_payload_length) nb_sections++;
     186             : 
     187          75 :         switch (table_id) {
     188          37 :         case GF_M2TS_TABLE_ID_PMT:
     189          37 :                 if (nb_sections > 1)
     190           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] last section number for PMT shall be 0\n"));
     191             :                 break;
     192             :         default:
     193             :                 break;
     194             :         }
     195             : 
     196             :         prev_sec = NULL;
     197             :         offset = 0;
     198         150 :         while (offset < table_payload_length) {
     199             :                 GF_BitStream *bs;
     200             :                 u32 remain;
     201          75 :                 GF_SAFEALLOC(section, GF_M2TS_Mux_Section);
     202          75 :                 if (!section) {
     203           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: fail to allocate section for table id %d\n", stream->pid, table_id));
     204             :                         return;
     205             :                 }
     206          75 :                 remain = table_payload_length - offset;
     207          75 :                 if (remain > maxSectionLength - overhead_size) {
     208           0 :                         section->length = maxSectionLength;
     209             :                 } else {
     210          75 :                         section->length = remain + overhead_size;
     211             :                 }
     212             : 
     213          75 :                 bs = gf_bs_new(NULL,0,GF_BITSTREAM_WRITE);
     214             : 
     215             :                 /* first header (not included in section length */
     216          75 :                 gf_bs_write_int(bs,     table_id, 8);
     217          75 :                 gf_bs_write_int(bs,     use_syntax_indicator, 1);
     218          75 :                 gf_bs_write_int(bs,     private_indicator, 1);
     219          75 :                 gf_bs_write_int(bs,     3, 2);  /* reserved bits are all set */
     220          75 :                 gf_bs_write_int(bs,     section->length - SECTION_HEADER_LENGTH, 12);
     221             : 
     222          75 :                 if (use_syntax_indicator) {
     223             :                         /* second header */
     224          75 :                         gf_bs_write_int(bs,     table_id_extension, 16);
     225          75 :                         gf_bs_write_int(bs,     3, 2); /* reserved bits are all set */
     226          75 :                         gf_bs_write_int(bs,     table->version_number, 5);
     227          75 :                         gf_bs_write_int(bs,     1, 1); /* current_next_indicator = 1: we don't send version in advance */
     228          75 :                         gf_bs_write_int(bs,     section_number, 8);
     229          75 :                         section_number++;
     230          75 :                         gf_bs_write_int(bs,     nb_sections-1, 8);
     231             :                 }
     232             : 
     233          75 :                 gf_bs_write_data(bs, (char *) table_payload + offset, section->length - overhead_size);
     234          75 :                 offset += section->length - overhead_size;
     235             : 
     236          75 :                 if (use_syntax_indicator) {
     237             :                         /* place holder for CRC */
     238          75 :                         gf_bs_write_u32(bs, 0);
     239             :                 }
     240             : 
     241          75 :                 gf_bs_get_content(bs, &section->data, &section->length);
     242          75 :                 gf_bs_del(bs);
     243             : 
     244          75 :                 if (use_syntax_indicator) {
     245             :                         u32 CRC;
     246          75 :                         CRC = gf_crc_32((char *) section->data,section->length-CRC_LENGTH);
     247          75 :                         section->data[section->length-4] = (CRC >> 24) & 0xFF;
     248          75 :                         section->data[section->length-3] = (CRC >> 16) & 0xFF;
     249          75 :                         section->data[section->length-2] = (CRC >> 8) & 0xFF;
     250          75 :                         section->data[section->length-1] = CRC & 0xFF;
     251             :                 }
     252             : 
     253          75 :                 if (prev_sec) prev_sec->next = section;
     254          75 :                 else table->section = section;
     255             :                 prev_sec = section;
     256             :         }
     257          75 :         stream->current_table = stream->tables;
     258          75 :         stream->current_section = stream->current_table->section;
     259          75 :         stream->current_section_offset = 0;
     260             : 
     261          75 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Generating %d sections for table id %d - version number %d - extension ID %d\n", stream->pid, nb_sections, table_id, table->version_number, table_id_extension));
     262             : }
     263             : 
     264       12680 : void gf_m2ts_mux_table_update_bitrate(GF_M2TS_Mux *mux, GF_M2TS_Mux_Stream *stream)
     265             : {
     266             :         GF_M2TS_Mux_Table *table;
     267             : 
     268             :         /*update PMT*/
     269       12680 :         if (stream->table_needs_update)
     270          75 :                 stream->process(mux, stream);
     271             : 
     272       12680 :         stream->bit_rate = 0;
     273       12680 :         table = stream->tables;
     274       38040 :         while (table) {
     275       12680 :                 GF_M2TS_Mux_Section *section = table->section;
     276       38040 :                 while (section) {
     277             :                         u32 nb_bytes = 0;
     278       12680 :                         while (nb_bytes<section->length) nb_bytes += 188;
     279       12680 :                         stream->bit_rate += nb_bytes;
     280       12680 :                         section = section->next;
     281             :                 }
     282       12680 :                 table = table->next;
     283             :         }
     284       12680 :         stream->bit_rate *= 8;
     285       12680 :         stream->bit_rate *= 1000;
     286       12680 :         if (stream->refresh_rate_ms) {
     287       12680 :                 stream->bit_rate /= stream->refresh_rate_ms;
     288           0 :         } else if (stream->table_needs_send) {
     289             :                 /*no clue ... */
     290           0 :                 stream->bit_rate /= 100;
     291             :         } else {
     292           0 :                 stream->bit_rate = 0;
     293             :         }
     294       12680 : }
     295             : 
     296           2 : void gf_m2ts_mux_table_update_mpeg4(GF_M2TS_Mux_Stream *stream, u8 table_id, u16 table_id_extension,
     297             :                                     char *table_payload, u32 table_payload_length,
     298             :                                     Bool use_syntax_indicator, Bool private_indicator,
     299             :                                     Bool increment_version_number, Bool use_checksum)
     300             : {
     301             :         GF_SLHeader hdr;
     302             :         u32 overhead_size;
     303             :         u32 offset, sl_size;
     304             :         u32 section_number, nb_sections;
     305             :         GF_M2TS_Mux_Table *table, *prev_table;
     306             :         /*max section length for MPEG-4 BIFS and OD*/
     307             :         u32 maxSectionLength = 4096;
     308             :         GF_M2TS_Mux_Section *section, *prev_sec;
     309             : 
     310             :         /* check if there is already a table with that id */
     311             :         prev_table = NULL;
     312           2 :         table = stream->tables;
     313           4 :         while (table) {
     314           0 :                 if (table->table_id == table_id) {
     315             :                         /* if yes, we need to flush the table and increase the version number */
     316           0 :                         GF_M2TS_Mux_Section *sec = table->section;
     317           0 :                         while (sec) {
     318           0 :                                 GF_M2TS_Mux_Section *sec2 = sec->next;
     319           0 :                                 gf_free(sec->data);
     320           0 :                                 gf_free(sec);
     321             :                                 sec = sec2;
     322             :                         }
     323           0 :                         if (increment_version_number)
     324           0 :                                 table->version_number = (table->version_number + 1)%0x1F;
     325             :                         break;
     326             :                 }
     327             :                 prev_table = table;
     328           0 :                 table = table->next;
     329             :         }
     330             : 
     331           2 :         if (!table) {
     332             :                 /* if no, the table is created */
     333           2 :                 GF_SAFEALLOC(table, GF_M2TS_Mux_Table);
     334           2 :                 if (!table) {
     335           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: fail to allocate table id %d\n", stream->pid, table_id));
     336           0 :                         return;
     337             :                 }
     338           2 :                 table->table_id = table_id;
     339           2 :                 if (prev_table) prev_table->next = table;
     340           2 :                 else stream->tables = table;
     341             :         }
     342             : 
     343           2 :         if (!table_payload_length) return;
     344             : 
     345             :         overhead_size = SECTION_HEADER_LENGTH;
     346           2 :         if (use_syntax_indicator) overhead_size += SECTION_ADDITIONAL_HEADER_LENGTH + CRC_LENGTH;
     347             : 
     348             :         section_number = 0;
     349             :         nb_sections = 1;
     350           2 :         hdr = stream->sl_header;
     351           2 :         sl_size = gf_sl_get_header_size(stream->ifce->sl_config, &hdr);
     352             :         /*SL-packetized data doesn't fit in one section, we must repacketize*/
     353           2 :         if (sl_size + table_payload_length > maxSectionLength - overhead_size) {
     354             :                 nb_sections = 0;
     355             :                 offset = 0;
     356           0 :                 hdr.accessUnitEndFlag = 0;
     357           0 :                 while (offset<table_payload_length) {
     358           0 :                         sl_size = gf_sl_get_header_size(stream->ifce->sl_config, &hdr);
     359             :                         /*remove start flag*/
     360           0 :                         hdr.accessUnitStartFlag = 0;
     361             :                         /*fill each section but beware of last packet*/
     362           0 :                         offset += maxSectionLength - overhead_size - sl_size;
     363           0 :                         nb_sections++;
     364             :                 }
     365             :         }
     366             :         prev_sec = NULL;
     367             :         offset = 0;
     368           2 :         hdr = stream->sl_header;
     369           6 :         while (offset < table_payload_length) {
     370             :                 GF_BitStream *bs;
     371             :                 u32 remain;
     372             :                 u8 *slhdr;
     373             :                 u32 slhdr_size;
     374           2 :                 GF_SAFEALLOC(section, GF_M2TS_Mux_Section);
     375           2 :                 if (!section) {
     376           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: fail to allocate section for table id %d\n", stream->pid, table_id));
     377           0 :                         return;
     378             :                 }
     379             : 
     380           2 :                 hdr.accessUnitEndFlag = (section_number+1==nb_sections) ? stream->sl_header.accessUnitEndFlag : 0;
     381           2 :                 gf_sl_packetize(stream->ifce->sl_config, &hdr, NULL, 0, &slhdr, &slhdr_size);
     382           2 :                 hdr.accessUnitStartFlag = 0;
     383             : 
     384           2 :                 remain = table_payload_length - offset;
     385           2 :                 if (remain > maxSectionLength - overhead_size - slhdr_size) {
     386           0 :                         section->length = maxSectionLength;
     387             :                 } else {
     388           2 :                         section->length = remain + overhead_size + slhdr_size;
     389             :                 }
     390           2 :                 sl_size = section->length - overhead_size - slhdr_size;
     391             : 
     392           2 :                 bs = gf_bs_new(NULL,0,GF_BITSTREAM_WRITE);
     393             : 
     394             :                 /* first header (not included in section length */
     395           2 :                 gf_bs_write_int(bs,     table_id, 8);
     396           2 :                 gf_bs_write_int(bs,     use_syntax_indicator, 1);
     397           2 :                 gf_bs_write_int(bs,     private_indicator, 1);
     398           2 :                 gf_bs_write_int(bs,     3, 2);  /* reserved bits are all set */
     399           2 :                 gf_bs_write_int(bs,     section->length - SECTION_HEADER_LENGTH, 12);
     400             : 
     401           2 :                 if (use_syntax_indicator) {
     402             :                         /* second header */
     403           2 :                         gf_bs_write_int(bs,     table_id_extension, 16);
     404           2 :                         gf_bs_write_int(bs,     3, 2); /* reserved bits are all set */
     405           2 :                         gf_bs_write_int(bs,     table->version_number, 5);
     406           2 :                         gf_bs_write_int(bs,     1, 1); /* current_next_indicator = 1: we don't send version in advance */
     407           2 :                         gf_bs_write_int(bs,     section_number, 8);
     408             :                         section_number++;
     409           2 :                         gf_bs_write_int(bs,     nb_sections-1, 8);
     410             :                 }
     411             : 
     412             :                 /*write sl header*/
     413           2 :                 gf_bs_write_data(bs, slhdr, slhdr_size);
     414           2 :                 gf_free(slhdr);
     415             :                 /*write sl data*/
     416           2 :                 gf_bs_write_data(bs, (char *) table_payload + offset, sl_size);
     417           2 :                 offset += sl_size;
     418             : 
     419           2 :                 if (use_syntax_indicator) {
     420             :                         /* place holder for CRC */
     421           2 :                         gf_bs_write_u32(bs, 0);
     422             :                 }
     423             : 
     424           2 :                 gf_bs_get_content(bs, &section->data, &section->length);
     425           2 :                 gf_bs_del(bs);
     426             : 
     427           2 :                 if (use_syntax_indicator) {
     428             :                         u32 CRC;
     429           2 :                         CRC = gf_crc_32((char *) section->data,section->length-CRC_LENGTH);
     430           2 :                         section->data[section->length-4] = (CRC >> 24) & 0xFF;
     431           2 :                         section->data[section->length-3] = (CRC >> 16) & 0xFF;
     432           2 :                         section->data[section->length-2] = (CRC >> 8) & 0xFF;
     433           2 :                         section->data[section->length-1] = CRC & 0xFF;
     434             :                 }
     435             : 
     436           2 :                 if (prev_sec) prev_sec->next = section;
     437           2 :                 else table->section = section;
     438             :                 prev_sec = section;
     439             :         }
     440           2 :         stream->current_table = stream->tables;
     441           2 :         stream->current_section = stream->current_table->section;
     442           2 :         stream->current_section_offset = 0;
     443           2 :         stream->table_needs_send = GF_TRUE;
     444             : 
     445           2 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Generating %d sections for MPEG-4 SL packet - version number %d - extension ID %d\n", stream->pid, nb_sections, table->version_number, table_id_extension));
     446             : 
     447             :         /*MPEG-4 tables are input streams for the mux, the bitrate is updated when fetching AUs*/
     448             : }
     449             : 
     450       21720 : static u32 gf_m2ts_add_adaptation(GF_M2TS_Mux_Program *prog, GF_BitStream *bs, u16 pid,
     451             :                                   Bool has_pcr, u64 pcr_time,
     452             :                                   Bool is_rap,
     453             :                                   u32 padding_length,
     454             :                                   char *af_descriptors, u32 af_descriptors_size, Bool set_discontinuity)
     455             : {
     456             :         u32 adaptation_length;
     457             : 
     458       21720 :         adaptation_length = ADAPTATION_FLAGS_LENGTH + (has_pcr?PCR_LENGTH:0) + padding_length;
     459             : 
     460             : 
     461       21720 :         if (af_descriptors_size && af_descriptors) {
     462         676 :                 adaptation_length += ADAPTATION_EXTENSION_LENGTH_LENGTH + ADAPTATION_EXTENSION_FLAGS_LENGTH + af_descriptors_size;
     463             :         }
     464             : 
     465       21720 :         gf_bs_write_int(bs,     adaptation_length, 8);
     466       21720 :         gf_bs_write_int(bs,     set_discontinuity ? 1 : 0, 1);                  // discontinuity indicator
     467       21720 :         gf_bs_write_int(bs,     is_rap, 1);             // random access indicator
     468       21720 :         gf_bs_write_int(bs,     0, 1);                  // es priority indicator
     469       21720 :         gf_bs_write_int(bs,     has_pcr, 1);    // PCR_flag
     470       21720 :         gf_bs_write_int(bs,     0, 1);                  // OPCR flag
     471       21720 :         gf_bs_write_int(bs,     0, 1);                  // splicing point flag
     472       21720 :         gf_bs_write_int(bs,     0, 1);                  // transport private data flag
     473       21720 :         gf_bs_write_int(bs,     af_descriptors_size ? 1 : 0, 1);                        // adaptation field extension flag
     474       21720 :         if (has_pcr) {
     475             :                 u64 PCR_base, PCR_ext;
     476       10675 :                 PCR_base = pcr_time/300;
     477       10675 :                 gf_bs_write_long_int(bs, PCR_base, 33);
     478       10675 :                 gf_bs_write_int(bs,     0, 6); // reserved
     479             :                 PCR_ext = pcr_time - PCR_base*300;
     480       10675 :                 gf_bs_write_long_int(bs, PCR_ext, 9);
     481       10675 :                 if (prog->last_pcr > pcr_time) {
     482           0 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Sending PCR "LLD" earlier than previous PCR "LLD" - drift %f sec - discontinuity set\n", pid, pcr_time, prog->last_pcr, (prog->last_pcr - pcr_time) /27000000.0 ));
     483             :                 }
     484       10675 :                 prog->last_pcr = pcr_time;
     485             : 
     486             : #ifndef GPAC_DISABLE_LOG
     487       10675 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Adding adaptation field size %d - RAP %d - Padding %d - PCR "LLD"\n", pid, adaptation_length, is_rap, padding_length, pcr_time));
     488             :         } else {
     489       11045 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Adding adaptation field size %d - RAP %d - Padding %d\n", pid, adaptation_length, is_rap, padding_length));
     490             : #endif
     491             : 
     492             :         }
     493             : 
     494       21720 :         if (af_descriptors_size) {
     495         676 :                 gf_bs_write_int(bs,     ADAPTATION_EXTENSION_FLAGS_LENGTH + af_descriptors_size, 8);
     496             : 
     497         676 :                 gf_bs_write_int(bs,     0, 1);                  // ltw_flag
     498         676 :                 gf_bs_write_int(bs,     0, 1);                  // piecewise_rate_flag
     499         676 :                 gf_bs_write_int(bs,     0, 1);                  // seamless_splice_flag
     500         676 :                 gf_bs_write_int(bs,     0, 1);                  // af_descriptor_not_present_flag
     501         676 :                 gf_bs_write_int(bs,     0xF, 4);                        // reserved
     502             : 
     503         676 :                 gf_bs_write_data(bs, af_descriptors, af_descriptors_size);
     504             :         }
     505             : 
     506       21720 :         gf_bs_write_byte(bs, 0xFF, padding_length); // stuffing byte
     507             : 
     508       21720 :         return adaptation_length + ADAPTATION_LENGTH_LENGTH;
     509             : }
     510             : 
     511             : //#define USE_AF_STUFFING
     512             : 
     513        4684 : void gf_m2ts_mux_table_get_next_packet(GF_M2TS_Mux *mux, GF_M2TS_Mux_Stream *stream, char *packet)
     514             : {
     515             :         GF_BitStream *bs;
     516             :         GF_M2TS_Mux_Table *table;
     517             :         GF_M2TS_Mux_Section *section;
     518             :         u32 payload_length, payload_start;
     519             :         u8 adaptation_field_control = GF_M2TS_ADAPTATION_NONE;
     520             : #ifndef USE_AF_STUFFING
     521             :         u32 padded_bytes=0;
     522             : #else
     523             :         u32 padding_length = 0;
     524             : #endif
     525             : 
     526        4684 :         stream->table_needs_send = GF_FALSE;
     527        4684 :         table = stream->current_table;
     528        4684 :         if (!table) {
     529           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] Invalid muxer state, table is NULL!\n"));
     530             :                 return;
     531             :         }
     532             : 
     533        4684 :         section = stream->current_section;
     534             :         assert(section);
     535             : 
     536        4684 :         bs = mux->pck_bs;
     537        4684 :         gf_bs_reassign_buffer(bs, packet, 188);
     538             : 
     539        4684 :         gf_bs_write_int(bs,     0x47, 8); // sync
     540        4684 :         gf_bs_write_int(bs,     0, 1);    // error indicator
     541        4684 :         if (stream->current_section_offset == 0) {
     542        4683 :                 gf_bs_write_int(bs,     1, 1);    // payload start indicator
     543             :         } else {
     544             :                 /* No section concatenation yet!!!*/
     545           1 :                 gf_bs_write_int(bs,     0, 1);    // payload start indicator
     546             :         }
     547             : 
     548        4684 :         if (!stream->current_section_offset) payload_length = 183;
     549             :         else payload_length = 184;
     550             : 
     551             :         payload_start = payload_length;
     552             : 
     553        4684 :         if (section->length - stream->current_section_offset >= payload_length) {
     554             : 
     555             :         } else  {
     556             :                 //stuffing using adaptation field - seems not well handled by some equipments ...
     557             : #ifdef USE_AF_STUFFING
     558             :                 /* in all the following cases, we write an adaptation field */
     559             :                 adaptation_field_control = GF_M2TS_ADAPTATION_AND_PAYLOAD;
     560             :                 /* we need at least 2 bytes for adaptation field headers (no pcr) */
     561             :                 payload_length -= 2;
     562             :                 if (section->length - stream->current_section_offset >= payload_length) {
     563             :                         padding_length = 0;
     564             :                 } else {
     565             :                         padding_length = payload_length - section->length + stream->current_section_offset;
     566             :                         payload_length -= padding_length;
     567             :                 }
     568             : #else
     569             :                 //stuffing according to annex C.3
     570        4683 :                 padded_bytes = payload_length - section->length + stream->current_section_offset;
     571             :                 payload_length = section->length - stream->current_section_offset;
     572             : #endif
     573             :         }
     574             : 
     575             :         assert(payload_length + stream->current_section_offset <= section->length);
     576             : 
     577             :         //CC field shall not be incremented for if adaptation field only, rewind counter
     578             :         if (adaptation_field_control == GF_M2TS_ADAPTATION_ONLY) {
     579             :                 if (!stream->continuity_counter) stream->continuity_counter=15;
     580             :                 else stream->continuity_counter--;
     581             :         }
     582             : 
     583        4684 :         gf_bs_write_int(bs,     0, 1);    /*priority indicator*/
     584        4684 :         gf_bs_write_int(bs,     stream->pid, 13); /*pid*/
     585        4684 :         gf_bs_write_int(bs,     0, 2);    /*scrambling indicator*/
     586        4684 :         gf_bs_write_int(bs,     adaptation_field_control, 2);    /*we do not use adaptation field for sections */
     587        4684 :         gf_bs_write_int(bs,     stream->continuity_counter, 4);   /*continuity counter*/
     588             : 
     589        4684 :         if (stream->continuity_counter < 15) stream->continuity_counter++;
     590         262 :         else stream->continuity_counter=0;
     591             : 
     592             : #ifdef USE_AF_STUFFING
     593             :         if (adaptation_field_control != GF_M2TS_ADAPTATION_NONE)
     594             :                 gf_m2ts_add_adaptation(stream->program, bs, stream->pid, 0, 0, 0, padding_length, NULL, 0, GF_FALSE);
     595             : #endif
     596             : 
     597             :         /*pointer field*/
     598        4684 :         if (!stream->current_section_offset) {
     599             :                 /* no concatenations of sections in ts packets, so start address is 0 */
     600        4683 :                 gf_bs_write_u8(bs, 0);
     601             :         }
     602             : 
     603        4684 :         memcpy(packet+188-payload_start, section->data + stream->current_section_offset, payload_length);
     604        4684 :         stream->current_section_offset += payload_length;
     605             : #ifndef USE_AF_STUFFING
     606        4684 :         if (padded_bytes) memset(packet+188-payload_start+payload_length, 0xFF, padded_bytes);
     607             : #endif
     608             : 
     609        4684 :         if (stream->current_section_offset == section->length) {
     610        4683 :                 stream->current_section_offset = 0;
     611        4683 :                 stream->current_section = stream->current_section->next;
     612        4683 :                 if (!stream->current_section) {
     613        4683 :                         stream->current_table = stream->current_table->next;
     614             :                         /*carousel table*/
     615        4683 :                         if (!stream->current_table) {
     616        4683 :                                 if (stream->ifce) stream->refresh_rate_ms = stream->ifce->repeat_rate;
     617        4683 :                                 if (stream->refresh_rate_ms) {
     618        4681 :                                         stream->current_table = stream->tables;
     619             :                                         /*update ES time*/
     620        4681 :                                         gf_m2ts_time_inc(&stream->time, stream->refresh_rate_ms, 1000);
     621             :                                 }
     622             :                         }
     623        4683 :                         if (stream->current_table) stream->current_section = stream->current_table->section;
     624             :                 }
     625             :         }
     626             :         /*updates number of bytes sent for bitrate compute (MPEG4 sections)*/
     627        4684 :         stream->bytes_since_last_time += 188;
     628             : }
     629             : 
     630             : 
     631        1165 : u32 gf_m2ts_stream_process_sdt(GF_M2TS_Mux *muxer, GF_M2TS_Mux_Stream *stream)
     632             : {
     633        1165 :         if (stream->table_needs_update) { /* generate table payload */
     634             :                 GF_M2TS_Mux_Program *prog;
     635             :                 GF_BitStream *bs;
     636             :                 u8 *payload;
     637             :                 u32 size;
     638             : 
     639           1 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     640             : 
     641           1 :                 gf_bs_write_u16(bs, muxer->ts_id);
     642           1 :                 gf_bs_write_u8(bs, 0xFF);       //reserved future use
     643             : 
     644           1 :                 prog = muxer->programs;
     645           3 :                 while (prog) {
     646             :                         u32 len = 0;
     647           1 :                         gf_bs_write_u16(bs, prog->number);
     648           1 :                         gf_bs_write_int(bs, 0xFF, 6); //reserved future use
     649           1 :                         gf_bs_write_int(bs, 0, 1); //EIT_schedule_flag
     650           1 :                         gf_bs_write_int(bs, 0, 1); //EIT_present_following_flag
     651           1 :                         gf_bs_write_int(bs, 4, 3); //running status
     652           1 :                         gf_bs_write_int(bs, 0, 1); //free_CA_mode
     653             : 
     654           1 :                         if (prog->name) len += (u32) strlen(prog->name);
     655           1 :                         if (prog->provider) len += (u32) strlen(prog->provider);
     656             : 
     657           1 :                         if (len) {
     658           1 :                                 len += 3;
     659           1 :                                 gf_bs_write_int(bs, len + 2, 12);
     660           1 :                                 gf_bs_write_u8(bs, GF_M2TS_DVB_SERVICE_DESCRIPTOR);
     661           1 :                                 gf_bs_write_u8(bs, len);
     662           1 :                                 gf_bs_write_u8(bs, 0x01);
     663           1 :                                 len = prog->provider ? (u32) strlen(prog->provider) : 0;
     664           1 :                                 gf_bs_write_u8(bs, len);
     665           1 :                                 if (prog->provider) gf_bs_write_data(bs, prog->provider, len);
     666             : 
     667           1 :                                 len = prog->name ? (u32) strlen(prog->name) : 0;
     668           1 :                                 gf_bs_write_u8(bs, len);
     669           1 :                                 if (prog->name) gf_bs_write_data(bs, prog->name, len);
     670             :                         } else {
     671           0 :                                 gf_bs_write_int(bs, 0, 12);
     672             :                         }
     673           1 :                         prog = prog->next;
     674             :                 }
     675           1 :                 gf_bs_get_content(bs, &payload, &size);
     676           1 :                 gf_bs_del(bs);
     677           1 :                 gf_m2ts_mux_table_update(stream, GF_M2TS_TABLE_ID_SDT_ACTUAL, muxer->ts_id, payload, size, GF_TRUE, GF_FALSE, GF_FALSE);
     678           1 :                 stream->table_needs_update = GF_FALSE;
     679           1 :                 stream->table_needs_send = GF_TRUE;
     680           1 :                 gf_free(payload);
     681             :         }
     682        1165 :         if (stream->table_needs_send)
     683             :                 return 1;
     684        1163 :         if (stream->refresh_rate_ms)
     685             :                 return 1;
     686           0 :         return 0;
     687             : }
     688             : 
     689      131667 : u32 gf_m2ts_stream_process_pat(GF_M2TS_Mux *muxer, GF_M2TS_Mux_Stream *stream)
     690             : {
     691      131667 :         if (stream->table_needs_update) { /* generate table payload */
     692             :                 GF_M2TS_Mux_Program *prog;
     693             :                 GF_BitStream *bs;
     694             :                 u8 *payload;
     695             :                 u32 size;
     696             : 
     697          37 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     698          37 :                 prog = muxer->programs;
     699         111 :                 while (prog) {
     700          37 :                         gf_bs_write_u16(bs, prog->number);
     701          37 :                         gf_bs_write_int(bs, 0x7, 3);    /*reserved*/
     702          37 :                         gf_bs_write_int(bs, prog->pmt->pid, 13);  /*reserved*/
     703          37 :                         prog = prog->next;
     704             :                 }
     705          37 :                 gf_bs_get_content(bs, &payload, &size);
     706          37 :                 gf_bs_del(bs);
     707          37 :                 gf_m2ts_mux_table_update(stream, GF_M2TS_TABLE_ID_PAT, muxer->ts_id, payload, size, GF_TRUE, GF_FALSE, GF_FALSE);
     708          37 :                 stream->table_needs_update = GF_FALSE;
     709          37 :                 stream->table_needs_send = GF_TRUE;
     710          37 :                 gf_free(payload);
     711             :         }
     712      131667 :         if (stream->table_needs_send)
     713             :                 return 1;
     714      131593 :         if (stream->refresh_rate_ms)
     715             :                 return 1;
     716           0 :         return 0;
     717             : }
     718             : 
     719      129319 : u32 gf_m2ts_stream_process_pmt(GF_M2TS_Mux *muxer, GF_M2TS_Mux_Stream *stream)
     720             : {
     721      129319 :         if (stream->table_needs_update) { /* generate table payload */
     722             :                 GF_M2TS_Mux_Stream *es;
     723             :                 u8 *payload;
     724             :                 u32 i;
     725             :                 u32 length, nb_streams=0;
     726             :                 u32 info_length = 0;
     727             :                 GF_BitStream *bs;
     728             : 
     729          37 :                 if (!stream->program->pcr)
     730           0 :                         abort();
     731             : 
     732          37 :                 bs = gf_bs_new(NULL,0,GF_BITSTREAM_WRITE);
     733          37 :                 gf_bs_write_int(bs,     0x7, 3); // reserved
     734          37 :                 gf_bs_write_int(bs,     stream->program->pcr->pid, 13);
     735          37 :                 gf_bs_write_int(bs,     0xF, 4); // reserved
     736             : 
     737             : 
     738          37 :                 if (stream->program->loop_descriptors) {
     739          39 :                         for (i=0; i<gf_list_count(stream->program->loop_descriptors); i++) {
     740           2 :                                 GF_M2TSDescriptor *desc = (GF_M2TSDescriptor*)gf_list_get(stream->program->loop_descriptors, i);
     741           2 :                                 info_length += 2 + desc->data_len;
     742             :                         }
     743             :                 }
     744             : 
     745          37 :                 if (!stream->program->iod) {
     746          36 :                         gf_bs_write_int(bs,     info_length, 12); // program info length =0
     747             :                 } else {
     748             :                         u32 len;
     749             :                         GF_ESD *esd;
     750             :                         GF_BitStream *bs_iod;
     751             :                         u8 *iod_data;
     752             :                         u32 iod_data_len;
     753             : 
     754             :                         /*rewrite SL config in IOD streams*/
     755           1 :                         i=0;
     756           4 :                         while (NULL != (esd = (GF_ESD*)gf_list_enum(((GF_ObjectDescriptor*)stream->program->iod)->ESDescriptors, &i))) {
     757           2 :                                 GF_M2TS_Mux_Stream *es_stream = stream->program->streams;
     758           7 :                                 while (es_stream) {
     759           5 :                                         if (es_stream->ifce && (es_stream->ifce->stream_id==esd->ESID)) {
     760             :                                                 /*thay should be the same ...*/
     761           2 :                                                 memcpy(esd->slConfig, es_stream->ifce->sl_config, sizeof(GF_SLConfig));
     762             :                                                 break;
     763             :                                         }
     764           3 :                                         es_stream = es_stream->next;
     765             :                                 }
     766             :                         }
     767             : 
     768           1 :                         bs_iod = gf_bs_new(NULL,0,GF_BITSTREAM_WRITE);
     769           1 :                         gf_odf_write_descriptor(bs_iod, stream->program->iod);
     770           1 :                         gf_bs_get_content(bs_iod, &iod_data, &iod_data_len);
     771           1 :                         gf_bs_del(bs_iod);
     772             : 
     773           1 :                         len = iod_data_len + 4;
     774           1 :                         gf_bs_write_int(bs,     len + info_length, 12); // program info length
     775             : 
     776           1 :                         gf_bs_write_int(bs,     GF_M2TS_MPEG4_IOD_DESCRIPTOR, 8);
     777           1 :                         len = iod_data_len + 2;
     778           1 :                         gf_bs_write_int(bs,     len, 8);
     779             : 
     780             :                         /* Scope_of_IOD_label :
     781             :                                 0x10 iod unique a l'int�rieur de programme
     782             :                                 0x11 iod unoque dans le flux ts */
     783           1 :                         gf_bs_write_int(bs,     2, 8);
     784             : 
     785           1 :                         gf_bs_write_int(bs,     2, 8);  // IOD_label
     786             : 
     787           1 :                         gf_bs_write_data(bs, iod_data, iod_data_len);
     788           1 :                         gf_free(iod_data);
     789             :                 }
     790             : 
     791             :                 /*write all other descriptors*/
     792          37 :                 if (stream->program->loop_descriptors) {
     793          39 :                         for (i=0; i<gf_list_count(stream->program->loop_descriptors); i++) {
     794           2 :                                 GF_M2TSDescriptor *desc = (GF_M2TSDescriptor*)gf_list_get(stream->program->loop_descriptors, i);
     795           2 :                                 gf_bs_write_int(bs,     desc->tag, 8);
     796           2 :                                 gf_bs_write_int(bs,     desc->data_len, 8);
     797           2 :                                 gf_bs_write_data(bs, desc->data, desc->data_len);
     798             :                         }
     799             :                 }
     800             : 
     801          37 :                 es = stream->program->streams;
     802         123 :                 while (es) {
     803             :                         Bool has_lang = GF_FALSE;
     804             :                         u32 es_info_length = 0;
     805          49 :                         u8 type = es->mpeg2_stream_type;
     806          49 :                         nb_streams++;
     807             : 
     808          49 :                         switch (es->mpeg2_stream_type) {
     809             :                         case GF_M2TS_AUDIO_AC3:
     810             :                         case GF_M2TS_VIDEO_VC1:
     811             :                                 es_info_length += 2 + 4;
     812             :                                 type = GF_M2TS_PRIVATE_DATA;
     813             :                                 break;
     814           0 :                         case GF_M2TS_AUDIO_EC3:
     815             :                                 es_info_length += 2;
     816             :                                 type = GF_M2TS_PRIVATE_DATA;
     817           0 :                                 break;
     818          47 :                         default:
     819          47 :                                 if (es->force_reg_desc) {
     820             :                                         es_info_length += 2 + 4 + 4;
     821             :                                         type = GF_M2TS_PRIVATE_DATA;
     822             :                                 }
     823             :                                 break;
     824             :                         }
     825             : 
     826          49 :                         gf_bs_write_int(bs,     type, 8);
     827          49 :                         gf_bs_write_int(bs,     0x7, 3); // reserved
     828          49 :                         gf_bs_write_int(bs,     es->pid, 13);
     829          49 :                         gf_bs_write_int(bs,     0xF, 4); // reserved
     830             : 
     831             :                         /*calculate es_info_length*/
     832          49 :                         if (stream->program->iod && es->ifce && !(es->ifce->caps & GF_ESI_STREAM_WITHOUT_MPEG4_SYSTEMS))
     833           3 :                                 es_info_length += 4;
     834             : 
     835             :                         /*another loop descriptors*/
     836          49 :                         if (es->loop_descriptors)
     837             :                         {
     838          52 :                                 for (i=0; i<gf_list_count(es->loop_descriptors); i++)
     839             :                                 {
     840           3 :                                         GF_M2TSDescriptor *desc = (GF_M2TSDescriptor*)gf_list_get(es->loop_descriptors, i);
     841           3 :                                         es_info_length += 2 +desc->data_len;
     842             :                                 }
     843             :                         }
     844             : 
     845          49 :                         if (es->ifce && es->ifce->lang && (es->ifce->lang != GF_LANG_UNKNOWN) ) {
     846           2 :                                 es_info_length += 2 + 3;
     847             :                                 has_lang = GF_TRUE;
     848             :                         }
     849             : 
     850          49 :                         gf_bs_write_int(bs,     es_info_length, 12);
     851             : 
     852          49 :                         if (stream->program->iod && es->ifce && !(es->ifce->caps & GF_ESI_STREAM_WITHOUT_MPEG4_SYSTEMS)) {
     853           3 :                                 gf_bs_write_int(bs,     GF_M2TS_MPEG4_SL_DESCRIPTOR, 8);
     854           3 :                                 gf_bs_write_int(bs,     2, 8);
     855           3 :                                 gf_bs_write_int(bs,     es->ifce->stream_id, 16);  // mpeg4_esid
     856             :                         }
     857             : 
     858          49 :                         if (has_lang) {
     859           2 :                                 gf_bs_write_int(bs,     GF_M2TS_ISO_639_LANGUAGE_DESCRIPTOR, 8);
     860           2 :                                 gf_bs_write_int(bs,     3, 8);
     861           2 :                                 gf_bs_write_int(bs,     (es->ifce->lang>>24) & 0xFF, 8);
     862           2 :                                 gf_bs_write_int(bs,     (es->ifce->lang>>16) & 0xFF, 8);
     863           2 :                                 gf_bs_write_int(bs,     es->ifce->lang & 0xFF, 8);
     864             :                         }
     865             : 
     866          49 :                         switch (es->mpeg2_stream_type) {
     867           2 :                         case GF_M2TS_AUDIO_AC3:
     868           2 :                                 gf_bs_write_int(bs,     GF_M2TS_REGISTRATION_DESCRIPTOR, 8);
     869           2 :                                 gf_bs_write_int(bs,     4, 8);
     870           2 :                                 gf_bs_write_int(bs,     'A', 8);
     871           2 :                                 gf_bs_write_int(bs,     'C', 8);
     872           2 :                                 gf_bs_write_int(bs,     '-', 8);
     873           2 :                                 gf_bs_write_int(bs,     '3', 8);
     874           2 :                                 break;
     875           0 :                         case GF_M2TS_VIDEO_VC1:
     876           0 :                                 gf_bs_write_int(bs,     GF_M2TS_REGISTRATION_DESCRIPTOR, 8);
     877           0 :                                 gf_bs_write_int(bs,     4, 8);
     878           0 :                                 gf_bs_write_int(bs,     'V', 8);
     879           0 :                                 gf_bs_write_int(bs,     'C', 8);
     880           0 :                                 gf_bs_write_int(bs,     '-', 8);
     881           0 :                                 gf_bs_write_int(bs,     '1', 8);
     882           0 :                                 break;
     883           0 :                         case GF_M2TS_AUDIO_EC3:
     884           0 :                                 gf_bs_write_int(bs,     GF_M2TS_DVB_EAC3_DESCRIPTOR, 8);
     885           0 :                                 gf_bs_write_int(bs,     0, 8); //check what is in this desc
     886           0 :                                 break;
     887          47 :                         default:
     888          47 :                                 if (es->force_reg_desc && es->ifce && es->ifce->codecid) {
     889           2 :                                         gf_bs_write_int(bs,     GF_M2TS_REGISTRATION_DESCRIPTOR, 8);
     890           2 :                                         gf_bs_write_int(bs,     8, 8);
     891           2 :                                         gf_bs_write_int(bs,     GF_M2TS_RA_STREAM_GPAC, 32);
     892           2 :                                         gf_bs_write_int(bs,     es->ifce->codecid, 32);
     893             :                                 }
     894             :                                 break;
     895             :                         }
     896             : 
     897          49 :                         if (es->loop_descriptors)
     898             :                         {
     899          52 :                                 for (i=0; i<gf_list_count(es->loop_descriptors); i++)
     900             :                                 {
     901           3 :                                         GF_M2TSDescriptor *desc = (GF_M2TSDescriptor *)gf_list_get(es->loop_descriptors, i);
     902           3 :                                         gf_bs_write_int(bs,     desc->tag, 8);
     903           3 :                                         gf_bs_write_int(bs,     desc->data_len, 8);
     904           3 :                                         gf_bs_write_data(bs, desc->data, desc->data_len);
     905             :                                 }
     906             :                         }
     907             : 
     908          49 :                         es = es->next;
     909             :                 }
     910             : 
     911          37 :                 gf_bs_get_content(bs, &payload, &length);
     912          37 :                 gf_bs_del(bs);
     913             : 
     914          37 :                 gf_m2ts_mux_table_update(stream, GF_M2TS_TABLE_ID_PMT, stream->program->number, payload, length, GF_TRUE, GF_FALSE, GF_FALSE);
     915          37 :                 stream->table_needs_update = GF_FALSE;
     916          37 :                 stream->table_needs_send = GF_TRUE;
     917          37 :                 gf_free(payload);
     918             : 
     919          37 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Updating PMT - Program Number %d - %d streams - size %d%s\n", stream->pid, stream->program->number, nb_streams, length, stream->program->iod ? " - MPEG-4 Systems detected":""));
     920             :         }
     921      129319 :         if (stream->table_needs_send)
     922             :                 return 1;
     923      129245 :         if (stream->refresh_rate_ms)
     924             :                 return 1;
     925           0 :         return 0;
     926             : }
     927             : 
     928       24107 : static void gf_m2ts_remap_timestamps_for_pes(GF_M2TS_Mux_Stream *stream, u32 pck_flags, u64 *dts, u64 *cts, u32 *duration)
     929             : {
     930             :         u64 pcr_offset;
     931             : 
     932       24107 :         if (*dts > *cts) {
     933           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: DTS "LLD" is greater than CTS "LLD" (like ISOBMF CTTSv1 input) - adjusting to CTS\n", stream->pid, *dts, *cts));
     934           0 :                 *dts = *cts;
     935             :         }
     936             : 
     937             :         /*Rescale our timestamps and express them in PCR*/
     938       24107 :         if (stream->ts_scale.den) {
     939       23916 :                 *cts = *cts * stream->ts_scale.num / stream->ts_scale.den ;
     940       23916 :                 *dts = *dts * stream->ts_scale.num / stream->ts_scale.den ;
     941       23916 :                 if (duration) *duration = (u32)( *duration * stream->ts_scale.num / stream->ts_scale.den ) ;
     942             :         }
     943       24107 :         if (!stream->program->initial_ts_set) {
     944          36 :                 u32 nb_bits = (u32) (stream->program->mux->tot_pck_sent - stream->program->num_pck_at_pcr_init) * 1504;
     945          36 :                 u64 nb_ticks = 90000*nb_bits / stream->program->mux->bit_rate;
     946          36 :                 stream->program->initial_ts = *dts;
     947             : 
     948          36 :                 if (stream->program->initial_ts > nb_ticks)
     949           0 :                         stream->program->initial_ts -= nb_ticks;
     950             :                 else
     951          36 :                         stream->program->initial_ts = 0;
     952             : 
     953          36 :                 stream->program->initial_ts_set = 1;
     954             :         }
     955       24071 :         else if ( (*dts < stream->program->initial_ts) && (stream->program->initial_ts_set==1)) {
     956           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: DTS "LLD" is less than initial DTS "LLD" - adjusting\n", stream->pid, *dts, stream->program->initial_ts));
     957           0 :                 stream->program->initial_ts = *dts;
     958             :         }
     959       24071 :         else if (*dts < stream->last_dts) {
     960           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: DTS "LLD" is less than last sent DTS "LLD"\n", stream->pid, *dts, stream->last_dts));
     961           0 :                 stream->last_dts = *dts;
     962             :         } else {
     963       24071 :                 stream->last_dts = *dts;
     964             :         }
     965             : 
     966             :         /*offset our timestamps*/
     967       24107 :         *cts += stream->program->pcr_offset;
     968       24107 :         *dts += stream->program->pcr_offset;
     969             : 
     970             :         /*PCR offset, in 90000 hz not in 270000000*/
     971       24107 :         pcr_offset = stream->program->pcr_init_time/300;
     972       24107 :         *cts = *cts - stream->program->initial_ts + pcr_offset;
     973       24107 :         *dts = *dts - stream->program->initial_ts + pcr_offset;
     974       24107 : }
     975             : 
     976          42 : void id3_write_size(GF_BitStream *bs, u32 len)
     977             : {
     978             :         u32 size;
     979             : 
     980          42 :         size = (len>>21) & 0x7F;
     981          42 :         gf_bs_write_int(bs, 0, 1);
     982          42 :         gf_bs_write_int(bs, size, 7);
     983             : 
     984          42 :         size = (len>>14) & 0x7F;
     985          42 :         gf_bs_write_int(bs, 0, 1);
     986          42 :         gf_bs_write_int(bs, size, 7);
     987             : 
     988          42 :         size = (len>>7) & 0x7F;
     989          42 :         gf_bs_write_int(bs, 0, 1);
     990          42 :         gf_bs_write_int(bs, size, 7);
     991             : 
     992          42 :         size = (len) & 0x7F;
     993          42 :         gf_bs_write_int(bs, 0, 1);
     994          42 :         gf_bs_write_int(bs, size, 7);
     995          42 : }
     996             : 
     997          21 : static void id3_tag_create(u8 **input, u32 *len)
     998             : {
     999          21 :         GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1000          21 :         gf_bs_write_u8(bs, 'I');
    1001          21 :         gf_bs_write_u8(bs, 'D');
    1002          21 :         gf_bs_write_u8(bs, '3');
    1003          21 :         gf_bs_write_u8(bs, 4); //major
    1004          21 :         gf_bs_write_u8(bs, 0); //minor
    1005          21 :         gf_bs_write_u8(bs, 0); //flags
    1006             : 
    1007          21 :         id3_write_size(bs, *len + 10);
    1008             : 
    1009          21 :         gf_bs_write_u32(bs, GF_ID3V2_FRAME_TXXX);
    1010          21 :         id3_write_size(bs, *len); /* size of the text */
    1011          21 :         gf_bs_write_u8(bs, 0);
    1012          21 :         gf_bs_write_u8(bs, 0);
    1013          21 :         gf_bs_write_data(bs, *input, *len);
    1014          21 :         gf_free(*input);
    1015          21 :         gf_bs_get_content(bs, input, len);
    1016          21 :         gf_bs_del(bs);
    1017          21 : }
    1018             : 
    1019       13232 : static Bool gf_m2ts_adjust_next_stream_time_for_pcr(GF_M2TS_Mux *muxer, GF_M2TS_Mux_Stream *stream)
    1020             : {
    1021             :         u32 pck_diff;
    1022             :         s32 us_diff;
    1023             :         GF_M2TS_Time next_pcr_time, stream_time;
    1024             : 
    1025       13232 :         if (!muxer->enable_forced_pcr) return 1;
    1026             : 
    1027         703 :         if (!muxer->bit_rate) return 1;
    1028             : 
    1029         703 :         next_pcr_time = stream->program->ts_time_at_pcr_init;
    1030         703 :         pck_diff = (u32) (stream->program->nb_pck_last_pcr - stream->program->num_pck_at_pcr_init);
    1031         703 :         gf_m2ts_time_inc(&next_pcr_time, pck_diff*1504, stream->program->mux->bit_rate);
    1032         703 :         gf_m2ts_time_inc(&next_pcr_time, stream->program->mux->pcr_update_ms, 1000);
    1033             : 
    1034         703 :         stream_time = stream->pcr_only_mode ? stream->next_time : stream->time;
    1035             :         //If next_pcr_time < stream->time, we need to inject pure pcr data
    1036             :         us_diff = gf_m2ts_time_diff_us(&next_pcr_time, &stream_time);
    1037         703 :         if (us_diff > 0) {
    1038         530 :                 if (!stream->pcr_only_mode) {
    1039          77 :                         stream->pcr_only_mode = GF_TRUE;
    1040          77 :                         stream->next_time = stream->time;
    1041             :                 }
    1042         530 :                 stream->time = next_pcr_time;
    1043             :                 /*if too ahead of mux time, don't insert PCR*/
    1044         530 :                 us_diff = gf_m2ts_time_diff_us(&stream->program->mux->time, &stream->time);
    1045         530 :                 if (us_diff>1000)
    1046             :                         return 0;
    1047         173 :         } else if (stream->pcr_only_mode) {
    1048          77 :                 stream->pcr_only_mode = GF_FALSE;
    1049          77 :                 stream->time = stream->next_time;
    1050             :         }
    1051             :         return 1;
    1052             : }
    1053             : 
    1054      201807 : static u32 gf_m2ts_stream_process_pes(GF_M2TS_Mux *muxer, GF_M2TS_Mux_Stream *stream)
    1055             : {
    1056             :         u64 time_inc;
    1057             :         Bool ret = GF_FALSE;
    1058             : 
    1059      201807 :         if (stream->mpeg2_stream_type==GF_M2TS_SYSTEMS_MPEG4_SECTIONS) {
    1060             :                 /*section has just been updated */
    1061        1058 :                 if (stream->table_needs_send)
    1062           5 :                         return stream->scheduling_priority;
    1063             :                 /*section is not completely sent yet or this is not the first section of the table*/
    1064        1053 :                 if (stream->current_section && (stream->current_section_offset || stream->current_section!=stream->current_table->section))
    1065           1 :                         return stream->scheduling_priority;
    1066        1052 :                 if (stream->ifce->repeat_rate && stream->tables)
    1067           0 :                         ret = stream->program->pcr_init_time ? stream->scheduling_priority : GF_FALSE;
    1068             :         }
    1069             :         /*PES packet not completely sent yet*/
    1070      200749 :         else if (stream->curr_pck.data_len && stream->pck_offset < stream->curr_pck.data_len) {
    1071             :                 //if in pure PCR mode, check if we can fall back to regular mode and start sending the stream
    1072      137756 :                 if ((stream == stream->program->pcr) && stream->pcr_only_mode) {
    1073         530 :                         if (! gf_m2ts_adjust_next_stream_time_for_pcr(muxer, stream)) {
    1074             :                                 return 0;
    1075             :                         }
    1076             :                 }
    1077      137506 :                 return stream->scheduling_priority;
    1078             :         }
    1079             : 
    1080             :         /*PULL mode*/
    1081       64045 :         if (stream->ifce->caps & GF_ESI_AU_PULL_CAP) {
    1082           0 :                 if (stream->curr_pck.data_len) {
    1083             :                         /*discard packet data if we use SL over PES*/
    1084           0 :                         if (stream->discard_data) gf_free(stream->curr_pck.data);
    1085           0 :                         if (stream->curr_pck.mpeg2_af_descriptors) gf_free(stream->curr_pck.mpeg2_af_descriptors);
    1086             :                         /*release data*/
    1087           0 :                         stream->ifce->input_ctrl(stream->ifce, GF_ESI_INPUT_DATA_RELEASE, NULL);
    1088             :                 }
    1089           0 :                 stream->pck_offset = 0;
    1090           0 :                 stream->curr_pck.data_len = 0;
    1091           0 :                 stream->discard_data = GF_FALSE;
    1092             : 
    1093             :                 /*EOS*/
    1094           0 :                 if (stream->ifce->caps & GF_ESI_STREAM_IS_OVER) return ret;
    1095             :                 assert(stream->ifce->input_ctrl);
    1096           0 :                 stream->ifce->input_ctrl(stream->ifce, GF_ESI_INPUT_DATA_PULL, &stream->curr_pck);
    1097             :         } else {
    1098             :                 GF_M2TS_Packet *curr_pck;
    1099             : 
    1100       64045 :                 if (!stream->pck_first && (stream->ifce->caps & GF_ESI_STREAM_IS_OVER))
    1101             :                         return ret;
    1102             : 
    1103             :                 /*flush input pipe*/
    1104       59051 :                 if (stream->ifce->input_ctrl) stream->ifce->input_ctrl(stream->ifce, GF_ESI_INPUT_DATA_FLUSH, NULL);
    1105             : 
    1106       59051 :                 if (stream->mx) gf_mx_p(stream->mx);
    1107             : 
    1108       59051 :                 stream->pck_offset = 0;
    1109       59051 :                 stream->curr_pck.data_len = 0;
    1110             : 
    1111             :                 /*fill curr_pck*/
    1112       59051 :                 curr_pck = stream->pck_first;
    1113       59051 :                 if (!stream->program->pcr_init_time_set && (stream != stream->program->pcr)) {
    1114             :                         curr_pck = NULL;
    1115             :                 }
    1116       59031 :                 if (!curr_pck) {
    1117       39199 :                         if (stream->mx) gf_mx_v(stream->mx);
    1118             :                         return ret;
    1119             :                 }
    1120       19852 :                 stream->curr_pck.cts = curr_pck->cts;
    1121       19852 :                 stream->curr_pck.data = curr_pck->data;
    1122       19852 :                 stream->curr_pck.data_len = curr_pck->data_len;
    1123       19852 :                 stream->curr_pck.dts = curr_pck->dts;
    1124       19852 :                 stream->curr_pck.duration = curr_pck->duration;
    1125       19852 :                 stream->curr_pck.flags = curr_pck->flags;
    1126       19852 :                 stream->curr_pck.sap_type = curr_pck->sap_type;
    1127       19852 :                 stream->curr_pck.mpeg2_af_descriptors = curr_pck->mpeg2_af_descriptors;
    1128       19852 :                 stream->curr_pck.mpeg2_af_descriptors_size = curr_pck->mpeg2_af_descriptors_size;
    1129             : 
    1130             :                 /*discard first packet*/
    1131       19852 :                 stream->pck_first = curr_pck->next;
    1132       19852 :                 gf_free(curr_pck);
    1133       19852 :                 stream->discard_data = GF_TRUE;
    1134             : 
    1135       19852 :                 if (stream->mx) gf_mx_v(stream->mx);
    1136             :         }
    1137             : 
    1138       19852 :         if (!(stream->curr_pck.flags & GF_ESI_DATA_HAS_DTS))
    1139       18140 :                 stream->curr_pck.dts = stream->curr_pck.cts;
    1140             : 
    1141             :         /*initializing the PCR*/
    1142       19852 :         if (!stream->program->pcr_init_time_set) {
    1143          37 :                 if (stream==stream->program->pcr) {
    1144          37 :                         if (stream->program->mux->init_pcr_value) {
    1145          37 :                                 stream->program->pcr_init_time = stream->program->mux->init_pcr_value-1;
    1146             :                         } else {
    1147           0 :                                 while (!stream->program->pcr_init_time)
    1148           0 :                                         stream->program->pcr_init_time = gf_rand();
    1149             :                         }
    1150             : 
    1151          37 :                         if (stream->program->force_first_pts) {
    1152           1 :                                 u64 first_pts = stream->curr_pck.cts;
    1153           1 :                                 u64 first_dts = stream->curr_pck.dts;
    1154             : 
    1155           1 :                                 if (stream->ts_scale.den) {
    1156           1 :                                         first_pts = first_pts * stream->ts_scale.num / stream->ts_scale.den;
    1157           1 :                                         first_dts = first_dts * stream->ts_scale.num / stream->ts_scale.den;
    1158             :                                 }
    1159             : 
    1160             :                                 /*the final PTS is computed by:
    1161             :                                         force_first_pts = first_pts + stream->program->pcr_offset - stream->program->initial_ts + stream->program->pcr_init_time/300;
    1162             :                                         force_first_dts = first_dts + stream->program->pcr_offset - stream->program->initial_ts + stream->program->pcr_init_time/300;
    1163             : 
    1164             :                                 time_inc is computed as
    1165             :                                         time_inc = force_first_dts - stream->program->pcr_init_time/300;
    1166             : 
    1167             :                                 =>   time_inc = first_dts + stream->program->pcr_offset - stream->program->initial_ts + stream->program->pcr_init_time/300 - stream->program->pcr_init_time/300;
    1168             : 
    1169             :                                 =>   time_inc = first_dts + stream->program->pcr_offset - stream->program->initial_ts;
    1170             : 
    1171             :                                         we want at the initial time_inc=0, hence
    1172             :                                         stream->program->initial_ts = first_dts + stream->program->pcr_offset;
    1173             : 
    1174             :                                 */
    1175             : /*
    1176             :                                 stream->program->pcr_init_time = first_dts*300 - stream->program->pcr_offset;
    1177             :                                 stream->program->initial_ts = first_pts + stream->program->pcr_offset + stream->program->pcr_init_time/300 - stream->program->force_first_pts;
    1178             : */
    1179             : 
    1180           1 :                                 stream->program->initial_ts = first_dts + stream->program->pcr_offset;
    1181           1 :                                 stream->program->pcr_init_time = 300 * (stream->program->force_first_pts - first_pts - stream->program->pcr_offset + stream->program->initial_ts);
    1182             : 
    1183           1 :                                 stream->program->initial_ts_set = 2;
    1184             :                         }
    1185             : 
    1186             : 
    1187          37 :                         stream->program->pcr_init_time_set = GF_TRUE;
    1188          37 :                         stream->program->ts_time_at_pcr_init = muxer->time;
    1189          37 :                         stream->program->num_pck_at_pcr_init = muxer->tot_pck_sent;
    1190             : 
    1191          37 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Initializing PCR for program number %d: PCR %d - mux time %d:%09d\n", stream->pid, stream->program->number, stream->program->pcr_init_time, muxer->time.sec, muxer->time.nanosec));
    1192             :                 } else {
    1193             :                         /*PES has been sent, discard internal buffer*/
    1194           0 :                         if (stream->discard_data) gf_free(stream->curr_pck.data);
    1195           0 :                         if (stream->curr_pck.mpeg2_af_descriptors) gf_free(stream->curr_pck.mpeg2_af_descriptors);
    1196           0 :                         stream->curr_pck.data = NULL;
    1197           0 :                         stream->curr_pck.data_len = 0;
    1198           0 :                         stream->curr_pck.mpeg2_af_descriptors = NULL;
    1199           0 :                         stream->curr_pck.mpeg2_af_descriptors_size = 0;
    1200           0 :                         stream->pck_offset = 0;
    1201             :                         /*don't send until PCR is initialized*/
    1202           0 :                         return 0;
    1203             :                 }
    1204             :         }
    1205             : 
    1206             :         /*SL-encapsultaion*/
    1207       19852 :         switch (stream->mpeg2_stream_type) {
    1208           2 :         case GF_M2TS_SYSTEMS_MPEG4_SECTIONS:
    1209             :                 /*update SL config*/
    1210           2 :                 stream->sl_header.accessUnitStartFlag = (stream->curr_pck.flags & GF_ESI_DATA_AU_START) ? 1 : 0;
    1211           2 :                 stream->sl_header.accessUnitEndFlag = (stream->curr_pck.flags & GF_ESI_DATA_AU_END) ? 1 : 0;
    1212             : #if 0
    1213             :                 assert(stream->sl_header.accessUnitLength + stream->curr_pck.data_len < 65536); /*stream->sl_header.accessUnitLength type is u16*/
    1214             :                 stream->sl_header.accessUnitLength += stream->curr_pck.data_len;
    1215             : #endif
    1216           2 :                 stream->sl_header.randomAccessPointFlag = (stream->curr_pck.sap_type) ? 1: 0;
    1217           2 :                 stream->sl_header.compositionTimeStampFlag = (stream->curr_pck.flags & GF_ESI_DATA_HAS_CTS) ? 1 : 0;
    1218           2 :                 stream->sl_header.compositionTimeStamp = stream->curr_pck.cts;
    1219           2 :                 stream->sl_header.decodingTimeStampFlag = (stream->curr_pck.flags & GF_ESI_DATA_HAS_DTS) ? 1: 0;
    1220           2 :                 stream->sl_header.decodingTimeStamp = stream->curr_pck.dts;
    1221             : 
    1222           2 :                 gf_m2ts_mux_table_update_mpeg4(stream, stream->table_id, muxer->ts_id, stream->curr_pck.data, stream->curr_pck.data_len, GF_TRUE, GF_FALSE, (stream->curr_pck.flags & GF_ESI_DATA_REPEAT) ? GF_FALSE : GF_TRUE, GF_FALSE);
    1223             : 
    1224             :                 /*packet data is now copied in sections, discard it if not pull*/
    1225           2 :                 if (!(stream->ifce->caps & GF_ESI_AU_PULL_CAP)) {
    1226           2 :                         gf_free(stream->curr_pck.data);
    1227           2 :                         stream->curr_pck.data = NULL;
    1228           2 :                         stream->curr_pck.data_len = 0;
    1229           2 :                         gf_free(stream->curr_pck.mpeg2_af_descriptors);
    1230           2 :                         stream->curr_pck.mpeg2_af_descriptors = NULL;
    1231           2 :                         stream->curr_pck.mpeg2_af_descriptors_size = 0;
    1232             :                 }
    1233             :                 break;
    1234           0 :         case GF_M2TS_SYSTEMS_MPEG4_PES:
    1235             :         {
    1236             :                 char *src_data;
    1237             :                 u32 src_data_len;
    1238             : 
    1239             :                 /*update SL config*/
    1240           0 :                 stream->sl_header.accessUnitStartFlag = (stream->curr_pck.flags & GF_ESI_DATA_AU_START) ? 1 : 0;
    1241           0 :                 stream->sl_header.accessUnitEndFlag = (stream->curr_pck.flags & GF_ESI_DATA_AU_END) ? 1 : 0;
    1242             : #if 0
    1243             :                 assert(stream->sl_header.accessUnitLength + stream->curr_pck.data_len < 65536); /*stream->sl_header.accessUnitLength type is u16*/
    1244             :                 stream->sl_header.accessUnitLength += stream->curr_pck.data_len;
    1245             : #endif
    1246           0 :                 stream->sl_header.randomAccessPointFlag = (stream->curr_pck.sap_type) ? 1: 0;
    1247           0 :                 stream->sl_header.compositionTimeStampFlag = (stream->curr_pck.flags & GF_ESI_DATA_HAS_CTS) ? 1 : 0;
    1248           0 :                 stream->sl_header.compositionTimeStamp = stream->curr_pck.cts;
    1249           0 :                 stream->sl_header.decodingTimeStampFlag = (stream->curr_pck.flags & GF_ESI_DATA_HAS_DTS) ? 1: 0;
    1250           0 :                 stream->sl_header.decodingTimeStamp = stream->curr_pck.dts;
    1251             : 
    1252           0 :                 src_data = stream->curr_pck.data;
    1253           0 :                 src_data_len = stream->curr_pck.data_len;
    1254           0 :                 stream->curr_pck.data_len = 0;
    1255           0 :                 stream->curr_pck.data = NULL;
    1256             : 
    1257           0 :                 gf_sl_packetize(stream->ifce->sl_config, &stream->sl_header, src_data, src_data_len, &stream->curr_pck.data, &stream->curr_pck.data_len);
    1258             : 
    1259             :                 /*discard src data*/
    1260           0 :                 if (!(stream->ifce->caps & GF_ESI_AU_PULL_CAP)) {
    1261           0 :                         gf_free(src_data);
    1262             :                 }
    1263           0 :                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Encapsulating MPEG-4 SL Data (%p - %p) on PES - SL Header size %d\n", stream->pid, src_data, stream->curr_pck.data, stream->curr_pck.data_len - src_data_len));
    1264             : 
    1265             :                 /*moving from PES to SL reallocates a new buffer, force discard even in pull mode*/
    1266           0 :                 stream->discard_data = GF_TRUE;
    1267             :         }
    1268           0 :         break;
    1269             :         /*perform LATM encapsulation*/
    1270           0 :         case GF_M2TS_AUDIO_LATM_AAC:
    1271             :         {
    1272             :                 u32 size, next_time;
    1273           0 :                 GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1274           0 :                 gf_bs_write_int(bs, 0x2B7, 11);
    1275           0 :                 gf_bs_write_int(bs, 0, 13);
    1276             : 
    1277             :                 /*same mux config = 0 (refresh aac config)*/
    1278           0 :                 next_time = gf_sys_clock();
    1279           0 :                 if (stream->ifce->decoder_config && (stream->latm_last_aac_time + stream->ifce->repeat_rate < next_time)) {
    1280             : #ifndef GPAC_DISABLE_AV_PARSERS
    1281             :                         GF_M4ADecSpecInfo cfg;
    1282             : #endif
    1283           0 :                         stream->latm_last_aac_time = next_time;
    1284             : 
    1285           0 :                         gf_bs_write_int(bs, 0, 1);
    1286             :                         /*mux config */
    1287           0 :                         gf_bs_write_int(bs, 0, 1);/*audio mux version = 0*/
    1288           0 :                         gf_bs_write_int(bs, 1, 1);/*allStreamsSameTimeFraming*/
    1289           0 :                         gf_bs_write_int(bs, 0, 6);/*numSubFrames*/
    1290           0 :                         gf_bs_write_int(bs, 0, 4);/*numProgram*/
    1291           0 :                         gf_bs_write_int(bs, 0, 3);/*numLayer prog 1*/
    1292             : 
    1293             : #ifndef GPAC_DISABLE_AV_PARSERS
    1294           0 :                         gf_m4a_get_config(stream->ifce->decoder_config, stream->ifce->decoder_config_size, &cfg);
    1295           0 :                         gf_m4a_write_config_bs(bs, &cfg);
    1296             : #else
    1297             :                         gf_bs_write_data(bs, stream->ifce->decoder_config, stream->ifce->decoder_config_size);
    1298             : #endif
    1299             : 
    1300           0 :                         gf_bs_write_int(bs, 0, 3);/*frameLengthType*/
    1301           0 :                         gf_bs_write_int(bs, 0, 8);/*latmBufferFullness*/
    1302           0 :                         gf_bs_write_int(bs, 0, 1);/*other data present*/
    1303           0 :                         gf_bs_write_int(bs, 0, 1);/*crcCheckPresent*/
    1304             :                 } else {
    1305           0 :                         gf_bs_write_int(bs, 1, 1);
    1306             :                 }
    1307             :                 /*write payloadLengthInfo*/
    1308           0 :                 size = stream->curr_pck.data_len;
    1309             :                 while (1) {
    1310           0 :                         if (size>=255) {
    1311           0 :                                 gf_bs_write_int(bs, 255, 8);
    1312           0 :                                 size -= 255;
    1313             :                         } else {
    1314           0 :                                 gf_bs_write_int(bs, size, 8);
    1315             :                                 break;
    1316             :                         }
    1317             :                 }
    1318           0 :                 stream->reframe_overhead = stream->curr_pck.data_len;
    1319           0 :                 gf_bs_write_data(bs, stream->curr_pck.data, stream->curr_pck.data_len);
    1320           0 :                 gf_bs_align(bs);
    1321           0 :                 gf_free(stream->curr_pck.data);
    1322           0 :                 gf_bs_get_content(bs, &stream->curr_pck.data, &stream->curr_pck.data_len);
    1323           0 :                 gf_bs_del(bs);
    1324           0 :                 stream->reframe_overhead = stream->curr_pck.data_len - stream->reframe_overhead;
    1325             : 
    1326             :                 /*rewrite LATM frame header*/
    1327           0 :                 size = stream->curr_pck.data_len - 2;
    1328           0 :                 stream->curr_pck.data[1] |= (size>>8) & 0x1F;
    1329           0 :                 stream->curr_pck.data[2] = (size) & 0xFF;
    1330             :                 /*since we reallocated the packet data buffer, force a discard in pull mode*/
    1331           0 :                 stream->discard_data = GF_TRUE;
    1332             :         }
    1333           0 :         break;
    1334             :         /*perform ADTS encapsulation*/
    1335       11895 :         case GF_M2TS_AUDIO_AAC:
    1336       11895 :                 if (stream->ifce->decoder_config) {
    1337             :                         GF_BitStream *bs;
    1338             : #ifndef GPAC_DISABLE_AV_PARSERS
    1339             :                         GF_M4ADecSpecInfo cfg;
    1340       11895 :                         gf_m4a_get_config(stream->ifce->decoder_config, stream->ifce->decoder_config_size, &cfg);
    1341       11895 :                         if (cfg.base_object_type>=5) cfg.base_object_type = GF_M4A_AAC_LC;
    1342             : #endif
    1343       11895 :                         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1344             : 
    1345             : 
    1346       11895 :                         gf_bs_write_int(bs, 0xFFF, 12);/*sync*/
    1347       11895 :                         gf_bs_write_int(bs, 0, 1);/*mpeg2 aac*/
    1348       11895 :                         gf_bs_write_int(bs, 0, 2); /*layer*/
    1349       11895 :                         gf_bs_write_int(bs, 1, 1); /* protection_absent*/
    1350             : #ifndef GPAC_DISABLE_AV_PARSERS
    1351       11895 :                         gf_bs_write_int(bs, cfg.base_object_type-1, 2);
    1352       11895 :                         gf_bs_write_int(bs, cfg.base_sr_index, 4);
    1353       11895 :                         gf_bs_write_int(bs, 0, 1);
    1354       11895 :                         if (cfg.program_config_element_present)
    1355           0 :                                 gf_bs_write_int(bs, 0, 3);
    1356             :                         else
    1357       11895 :                                 gf_bs_write_int(bs, cfg.chan_cfg, 3);
    1358             : #else
    1359             :                         gf_bs_write_int(bs, GF_M4A_AAC_LC-1, 2);
    1360             :                         gf_bs_write_int(bs, 1, 4); //FIXME
    1361             :                         gf_bs_write_int(bs, 0, 1);
    1362             :                         gf_bs_write_int(bs, 2, 3);//FIXME
    1363             : #endif
    1364             : 
    1365       11895 :                         gf_bs_write_int(bs, 0, 4);
    1366       11895 :                         gf_bs_write_int(bs, 7+stream->curr_pck.data_len, 13);
    1367       11895 :                         gf_bs_write_int(bs, 0x7FF, 11);
    1368             : 
    1369             :                         /*base reframe overhead*/
    1370       11895 :                         stream->reframe_overhead = 7;
    1371             : 
    1372             : #ifndef GPAC_DISABLE_AV_PARSERS
    1373       11895 :                         if (cfg.program_config_element_present) {
    1374           0 :                                 gf_bs_write_int(bs, 2, 2);
    1375             : 
    1376           0 :                                 u32 cpe_size = (u32) gf_bs_get_position(bs);
    1377           0 :                                 gf_m4a_write_program_config_element_bs(bs, &cfg);
    1378           0 :                                 stream->reframe_overhead += (u32) gf_bs_get_position(bs) - cpe_size;
    1379             :                         } else
    1380             : #endif
    1381       11895 :                                 gf_bs_write_int(bs, 0, 2);
    1382             : 
    1383             : 
    1384       11895 :                         gf_bs_write_data(bs, stream->curr_pck.data, stream->curr_pck.data_len);
    1385       11895 :                         gf_bs_align(bs);
    1386       11895 :                         gf_free(stream->curr_pck.data);
    1387       11895 :                         gf_bs_get_content(bs, &stream->curr_pck.data, &stream->curr_pck.data_len);
    1388       11895 :                         gf_bs_del(bs);
    1389             :                 }
    1390             :                 /*since we reallocated the packet data buffer, force a discard in pull mode*/
    1391       11895 :                 stream->discard_data = GF_TRUE;
    1392       11895 :                 break;
    1393          21 :         case GF_M2TS_METADATA_PES:
    1394             :         case GF_M2TS_METADATA_ID3_HLS:
    1395             :         {
    1396          21 :                 id3_tag_create(&stream->curr_pck.data, &stream->curr_pck.data_len);
    1397          21 :                 stream->discard_data = GF_TRUE;
    1398             :         }
    1399          21 :                 break;
    1400             :         default:
    1401             :                 break;
    1402             :         }
    1403             : 
    1404       19852 :         if (stream->start_pes_at_rap && (stream->curr_pck.sap_type)
    1405             :            ) {
    1406           0 :                 stream->program->mux->force_pat = GF_TRUE;
    1407             :         }
    1408             : 
    1409             :         /*rewrite timestamps for PES header*/
    1410       19852 :         gf_m2ts_remap_timestamps_for_pes(stream, stream->curr_pck.flags, &stream->curr_pck.dts, &stream->curr_pck.cts, &stream->curr_pck.duration);
    1411             : 
    1412             :         /*compute next interesting time in TS unit: this will be DTS of next packet*/
    1413       19852 :         stream->time = stream->program->ts_time_at_pcr_init;
    1414       19852 :         time_inc = stream->curr_pck.dts - stream->program->pcr_init_time/300;
    1415             : 
    1416             :         gf_m2ts_time_inc(&stream->time, time_inc, 90000);
    1417             : 
    1418       19852 :         if (stream == stream->program->pcr) {
    1419       12702 :                 gf_m2ts_adjust_next_stream_time_for_pcr(muxer, stream);
    1420             :         }
    1421             : 
    1422       19852 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Next data schedule for %d:%09d - mux time %d:%09d\n", stream->pid, stream->time.sec, stream->time.nanosec, muxer->time.sec, muxer->time.nanosec));
    1423             : 
    1424             :         /*compute instant bitrate*/
    1425       19852 :         if (!stream->last_br_time) {
    1426         581 :                 stream->last_br_time = stream->curr_pck.dts + 1;
    1427         581 :                 stream->bytes_since_last_time = 0;
    1428         581 :                 stream->pes_since_last_time = 0;
    1429             :         } else {
    1430       19271 :                 u32 time_diff = (u32) (stream->curr_pck.dts + 1 - stream->last_br_time );
    1431       19271 :                 if ((stream->pes_since_last_time > 4) && (time_diff >= BITRATE_UPDATE_WINDOW)) {
    1432             :                         u32 bitrate;
    1433         533 :                         u64 r = 8*stream->bytes_since_last_time;
    1434         533 :                         r*=90000;
    1435         533 :                         bitrate = (u32) (r / time_diff);
    1436             : 
    1437         533 :                         if (stream->program->mux->fixed_rate || (stream->bit_rate < bitrate)) {
    1438         133 :                                 stream->bit_rate = bitrate;
    1439         133 :                                 stream->program->mux->needs_reconfig = GF_TRUE;
    1440             :                         }
    1441         533 :                         stream->last_br_time = 0;
    1442         533 :                         stream->bytes_since_last_time = 0;
    1443         533 :                         stream->pes_since_last_time = 0;
    1444             :                 }
    1445             :         }
    1446             : 
    1447       19852 :         stream->pes_since_last_time ++;
    1448       19852 :         return stream->scheduling_priority;
    1449             : }
    1450             : 
    1451             : static GFINLINE u64 gf_m2ts_get_pcr(GF_M2TS_Mux_Stream *stream)
    1452             : {
    1453             :         u64 pcr;
    1454             :         /*compute PCR*/
    1455       30395 :         if (stream->program->mux->fixed_rate) {
    1456         676 :                 Double abs_pcr = (Double) (stream->program->mux->tot_pck_sent - stream->program->num_pck_at_pcr_init);
    1457         676 :                 abs_pcr *= 27000000;
    1458         676 :                 abs_pcr *= 1504;
    1459         676 :                 abs_pcr /= stream->program->mux->bit_rate;
    1460         676 :                 pcr = (u64) abs_pcr + stream->program->pcr_init_time;
    1461             :         }
    1462             :         /*in non-realtime mode with no fixed rate we only insert PCR based on DTS */
    1463             :         else {
    1464       29719 :                 pcr = (stream->curr_pck.dts - stream->program->pcr_offset) * 300;
    1465             :         }
    1466             :         return pcr;
    1467             : }
    1468             : 
    1469       15827 : void gf_m2ts_stream_update_data_following(GF_M2TS_Mux_Stream *stream)
    1470             : {
    1471             :         Bool ignore_next = GF_FALSE;
    1472       15827 :         stream->next_payload_size = 0;
    1473       15827 :         stream->next_next_payload_size = 0;
    1474       15827 :         stream->next_next_next_payload_size = 0;
    1475             : 
    1476       15827 :         stream->next_pck_flags = 0;
    1477       15827 :         stream->next_pck_sap = 0;
    1478       15827 :         stream->copy_from_next_packets = 0;
    1479             : 
    1480             :         //AU packing in single PES is disabled
    1481       15827 :         if (stream->force_single_au) return;
    1482             : 
    1483        4506 :         if (stream->ifce->caps & GF_ESI_AU_PULL_CAP) {
    1484             :                 GF_ESIPacket test_pck;
    1485           0 :                 test_pck.data_len = 0;
    1486             :                 /*pull next data but do not release it since it might be needed later on*/
    1487           0 :                 stream->ifce->input_ctrl(stream->ifce, GF_ESI_INPUT_DATA_PULL, &test_pck);
    1488           0 :                 if (test_pck.data_len) {
    1489           0 :                         stream->next_payload_size = test_pck.data_len;
    1490           0 :                         stream->next_pck_flags = test_pck.flags;
    1491           0 :                         stream->next_pck_sap = test_pck.sap_type;
    1492           0 :                         stream->next_pck_cts = test_pck.cts;
    1493           0 :                         stream->next_pck_dts = test_pck.dts;
    1494             :                 }
    1495             :         } else {
    1496             :                 /*flush input*/
    1497        4506 :                 if (!stream->pck_first && stream->ifce->input_ctrl) stream->ifce->input_ctrl(stream->ifce, GF_ESI_INPUT_DATA_FLUSH, NULL);
    1498        4506 :                 if (stream->pck_first) {
    1499        4341 :                         stream->next_payload_size = stream->pck_first->data_len;
    1500        4341 :                         stream->next_pck_cts = stream->pck_first->cts;
    1501        4341 :                         stream->next_pck_dts = stream->pck_first->dts;
    1502        4341 :                         stream->next_pck_flags = stream->pck_first->flags;
    1503        4341 :                         stream->next_pck_sap = stream->pck_first->sap_type;
    1504             : 
    1505        4341 :                         if (!stream->pck_first->next && stream->ifce->input_ctrl) stream->ifce->input_ctrl(stream->ifce, GF_ESI_INPUT_DATA_FLUSH, NULL);
    1506        4341 :                         if (stream->pck_first->next) {
    1507        3988 :                                 stream->next_next_payload_size = stream->pck_first->next->data_len;
    1508        3988 :                                 if (!stream->pck_first->next->next && stream->ifce->input_ctrl) stream->ifce->input_ctrl(stream->ifce, GF_ESI_INPUT_DATA_FLUSH, NULL);
    1509        3988 :                                 if (stream->pck_first->next->next) {
    1510        3928 :                                         stream->next_next_next_payload_size = stream->pck_first->next->next->data_len;
    1511             :                                 }
    1512             :                         }
    1513             :                 }
    1514             :         }
    1515             :         /*consider we don't have the next AU if:
    1516             :         1- we are asked to start new PES at RAP, just consider we don't have the next AU*/
    1517        4506 :         if (stream->start_pes_at_rap && stream->next_pck_sap) {
    1518             :                 ignore_next = GF_TRUE;
    1519             : //              stream->program->mux->force_pat_pmt_state = GF_SEG_BOUNDARY_START;
    1520             :         }
    1521             :         /*if we have a RAP about to start on a stream in this program, force all other streams to stop merging data in their current PES*/
    1522        4506 :         else if (stream->program->mux->force_pat_pmt_state) {
    1523             :                 ignore_next = GF_TRUE;
    1524             :         }
    1525             : 
    1526             :         if (ignore_next) {
    1527          88 :                 stream->next_payload_size = 0;
    1528          88 :                 stream->next_pck_cts = 0;
    1529          88 :                 stream->next_pck_dts = 0;
    1530          88 :                 stream->next_pck_flags = 0;
    1531          88 :                 stream->next_pck_sap = 0;
    1532             :         }
    1533             : 
    1534        4506 :         if (stream->next_payload_size) {
    1535        4255 :                 stream->next_payload_size += stream->reframe_overhead;
    1536        4255 :                 if (stream->next_next_payload_size) {
    1537        3902 :                         stream->next_next_payload_size += stream->reframe_overhead;
    1538        3902 :                         if (stream->next_next_next_payload_size) {
    1539        3842 :                                 stream->next_next_next_payload_size += stream->reframe_overhead;
    1540             :                         }
    1541             :                 }
    1542             : 
    1543        4255 :                 gf_m2ts_remap_timestamps_for_pes(stream, stream->next_pck_flags, &stream->next_pck_dts, &stream->next_pck_cts, NULL);
    1544             : 
    1545             : 
    1546        4255 :                 if (!(stream->next_pck_flags & GF_ESI_DATA_HAS_DTS))
    1547        4255 :                         stream->next_pck_dts = stream->next_pck_cts;
    1548             :         }
    1549             : }
    1550             : 
    1551             : 
    1552       15853 : Bool gf_m2ts_stream_compute_pes_length(GF_M2TS_Mux_Stream *stream, u32 payload_length)
    1553             : {
    1554             :         assert(stream->pes_data_remain==0);
    1555       15853 :         stream->pes_data_len = stream->curr_pck.data_len - stream->pck_offset;
    1556             : 
    1557       15853 :         stream->copy_from_next_packets = 0;
    1558             :         /*if we have next payload ready, compute transmitted size*/
    1559       15853 :         if (stream->next_payload_size) {
    1560             :                 u32 pck_size = stream->curr_pck.data_len - stream->pck_offset;
    1561             :                 u32 ts_bytes = payload_length;
    1562             : 
    1563             :                 /*finish this AU*/
    1564        5283 :                 while (ts_bytes < pck_size) {
    1565        1028 :                         ts_bytes += 184;
    1566             :                 }
    1567             : 
    1568             :                 /*current AU started in PES, don't start new AU - if enough data
    1569             :                 still to be sent from current AU, don't send the complete AU
    1570             :                 in order to avoid padding*/
    1571        4255 :                 if (stream->prevent_two_au_start_in_pes && !stream->pck_offset) {
    1572           0 :                         if (ts_bytes>184)
    1573           0 :                                 ts_bytes -= 184;
    1574             :                         else
    1575             :                                 ts_bytes = pck_size;
    1576             :                 }
    1577             :                 /*try to fit in part of the next AU*/
    1578             :                 else if (stream->next_payload_size) {
    1579             :                         /*how much more TS packets do we need to send next AU ?*/
    1580        8443 :                         while (ts_bytes < pck_size + stream->next_payload_size) {
    1581             :                                 //check we have enough bytes in the next 3 AUs if we increase by 1 TS packet the PES
    1582             :                                 //bytes_to_copy from next will be: ts_bytes + 184 - pck_size
    1583             :                                 //check bytes_to_copy is <= next_payload_size + next_next_payload_size + next_next_next_payload_size
    1584             :                                 //if not, do not add - we do not want to take the risk of having no data while filling a PES packet with an announced length
    1585        4535 :                                 if (ts_bytes + 184 > pck_size + stream->next_payload_size + stream->next_next_payload_size + stream->next_next_next_payload_size)
    1586             :                                         break;
    1587             : 
    1588             :                                 ts_bytes += 184;
    1589             :                         }
    1590             :                         /*don't end next AU in next PES if we don't want to start 2 AUs in one PES
    1591             :                         if we don't have the N+2 AU size, don't try to pack it*/
    1592        4255 :                         if ((stream->prevent_two_au_start_in_pes && (ts_bytes>pck_size + stream->next_payload_size))
    1593        4255 :                                 || !stream->next_next_payload_size
    1594             :                            ) {
    1595         353 :                                 if (ts_bytes>184)
    1596         154 :                                         ts_bytes -= 184;
    1597             :                                 else
    1598             :                                         ts_bytes = pck_size + stream->next_payload_size;
    1599             :                         }
    1600             :                 }
    1601             : 
    1602             :                 /*that's how much bytes we copy from the following AUs*/
    1603        4255 :                 if (ts_bytes >= pck_size) {
    1604        4115 :                         stream->copy_from_next_packets = ts_bytes - pck_size;
    1605             :                         //very low rate case, we didn't enter the previous while loop:
    1606             :                         //we can't fill the complete TS packet with the next two AUs, do not copy over
    1607        4115 :                         if (stream->copy_from_next_packets > stream->next_payload_size + stream->next_next_payload_size + stream->next_next_next_payload_size)
    1608           0 :                                 stream->copy_from_next_packets = 0;
    1609             :                 } else {
    1610         140 :                         u32 skipped = pck_size-ts_bytes;
    1611         140 :                         if (stream->pes_data_len > skipped)
    1612         140 :                                 stream->pes_data_len -= skipped;
    1613             :                 }
    1614             : 
    1615        4255 :                 if (stream->min_bytes_copy_from_next && stream->copy_from_next_packets) {
    1616             :                         /*if we don't have enough space in the PES to store beginning of new AU, don't copy it and ask
    1617             :                         to recompute header (we might no longer have DTS/CTS signaled)*/
    1618           0 :                         if (stream->copy_from_next_packets < stream->min_bytes_copy_from_next) {
    1619           0 :                                 stream->copy_from_next_packets = 0;
    1620           0 :                                 stream->next_payload_size = 0;
    1621           0 :                                 stream->next_pck_flags = 0;
    1622           0 :                                 stream->next_pck_sap = 0;
    1623           0 :                                 return GF_FALSE;
    1624             :                         }
    1625             :                         /*if what will remain after copying next AU is less than the minimum safety copy only copy next AU and
    1626             :                         realign n+2 AU start with PES*/
    1627           0 :                         if ((stream->copy_from_next_packets > stream->next_payload_size)
    1628           0 :                                 && (stream->copy_from_next_packets - stream->next_payload_size < stream->min_bytes_copy_from_next)
    1629             :                            ) {
    1630           0 :                                 stream->copy_from_next_packets = stream->next_payload_size;
    1631             :                         }
    1632             :                 }
    1633             : 
    1634        4255 :                 if (stream->pck_offset && !stream->copy_from_next_packets && stream->next_payload_size) {
    1635          26 :                         stream->copy_from_next_packets = 0;
    1636          26 :                         stream->next_payload_size = 0;
    1637          26 :                         stream->next_pck_flags = 0;
    1638          26 :                         stream->next_pck_sap = 0;
    1639          26 :                         return GF_FALSE;
    1640             :                 }
    1641             : 
    1642        4229 :                 if (stream->ifce->caps & GF_ESI_STREAM_IS_OVER) {
    1643             : #if 0
    1644             :                         while (stream->copy_from_next_packets > stream->next_payload_size) {
    1645             :                                 if (stream->copy_from_next_packets < 184) {
    1646             :                                         stream->copy_from_next_packets = 0;
    1647             :                                         break;
    1648             :                                 }
    1649             :                                 stream->copy_from_next_packets -= 184;
    1650             :                         }
    1651             : #endif
    1652           3 :                         stream->pes_data_len += stream->next_payload_size;
    1653             :                 } else {
    1654        4226 :                         stream->pes_data_len += stream->copy_from_next_packets;
    1655             :                 }
    1656             :         }
    1657       15827 :         stream->pes_data_remain = stream->pes_data_len;
    1658       15827 :         return GF_TRUE;
    1659             : }
    1660             : 
    1661             : static u32 gf_m2ts_stream_get_pes_header_length(GF_M2TS_Mux_Stream *stream)
    1662             : {
    1663             :         u32 hdr_len, flags;
    1664      134199 :         flags = stream->pck_offset ? stream->next_pck_flags : stream->curr_pck.flags;
    1665             : 
    1666             :         /*not done with the current pes*/
    1667      134199 :         if (stream->pes_data_remain) return 0;
    1668             :         hdr_len = 9;
    1669             :         /*signal timing only if AU start in the PES*/
    1670       31680 :         if ( flags & GF_ESI_DATA_AU_START) {
    1671       31583 :                 if (flags & GF_ESI_DATA_HAS_CTS) hdr_len += 5;
    1672       31583 :                 if (flags & GF_ESI_DATA_HAS_DTS) hdr_len += 5;
    1673             :         }
    1674             :         return hdr_len;
    1675             : }
    1676             : 
    1677       15827 : u32 gf_m2ts_stream_add_pes_header(GF_BitStream *bs, GF_M2TS_Mux_Stream *stream)
    1678             : {
    1679             :         u64 t, dts, cts;
    1680             :         u32 pes_len;
    1681             :         Bool use_pts, use_dts;
    1682             : 
    1683       15827 :         gf_bs_write_int(bs,     0x1, 24);//packet start code
    1684       15827 :         gf_bs_write_u8(bs,      stream->mpeg2_stream_id);// stream id
    1685             : 
    1686             :         /*next AU start in current PES and current AU began in previous PES, use next AU timing*/
    1687       15827 :         if (stream->pck_offset && stream->copy_from_next_packets) {
    1688        3909 :                 use_pts = (stream->next_pck_flags & GF_ESI_DATA_HAS_CTS) ? GF_TRUE : GF_FALSE;
    1689        3909 :                 use_dts = (stream->next_pck_flags & GF_ESI_DATA_HAS_DTS) ? GF_TRUE : GF_FALSE;
    1690        3909 :                 dts = stream->next_pck_dts;
    1691        3909 :                 cts = stream->next_pck_cts;
    1692             :         }
    1693             :         /*we already sent the beginning of the AU*/
    1694       11918 :         else if (stream->pck_offset) {
    1695             :                 use_pts = use_dts = GF_FALSE;
    1696             :                 dts = cts = 0;
    1697             :         } else {
    1698       11821 :                 use_pts = (stream->curr_pck.flags & GF_ESI_DATA_HAS_CTS) ? GF_TRUE : GF_FALSE;
    1699       11821 :                 use_dts = (stream->curr_pck.flags & GF_ESI_DATA_HAS_DTS) ? GF_TRUE : GF_FALSE;
    1700       11821 :                 dts = stream->curr_pck.dts;
    1701       11821 :                 cts = stream->curr_pck.cts;
    1702             :         }
    1703             : 
    1704             :         /*PES packet length: number of bytes in the PES packet following the last byte of the field "pes packet length"*/
    1705             :         assert(stream->pes_data_len);
    1706       15827 :         pes_len = stream->pes_data_len + 3; // 3 = header size
    1707       15827 :         if (use_pts) pes_len += 5;
    1708       15827 :         if (use_dts) pes_len += 5;
    1709             : 
    1710       15827 :         if (pes_len>0xFFFF) pes_len = 0;
    1711       15827 :         gf_bs_write_int(bs, pes_len, 16); // pes packet length
    1712             : 
    1713       15827 :         gf_bs_write_int(bs, 0x2, 2); // reserved
    1714       15827 :         gf_bs_write_int(bs, 0x0, 2); // scrambling
    1715       15827 :         gf_bs_write_int(bs, 0x0, 1); // priority
    1716       15827 :         gf_bs_write_int(bs, stream->pck_offset ? 0 : 1, 1); // alignment indicator - we could also check start codes to see if we are aligned at slice/video packet level
    1717       15827 :         gf_bs_write_int(bs, 0x0, 1); // copyright
    1718       15827 :         gf_bs_write_int(bs, 0x0, 1); // original or copy
    1719             : 
    1720       15827 :         gf_bs_write_int(bs, use_pts, 1);
    1721       15827 :         gf_bs_write_int(bs, use_dts, 1);
    1722       15827 :         gf_bs_write_int(bs, 0x0, 6); //6 flags = 0 (ESCR, ES_rate, DSM_trick, additional_copy, PES_CRC, PES_extension)
    1723             : 
    1724       15827 :         gf_bs_write_int(bs, use_dts*5+use_pts*5, 8);
    1725             : 
    1726       15827 :         if (use_pts) {
    1727       15730 :                 gf_bs_write_int(bs, use_dts ? 0x3 : 0x2, 4); // reserved '0011' || '0010'
    1728       15730 :                 t = ((cts >> 30) & 0x7);
    1729       15730 :                 gf_bs_write_long_int(bs, t, 3);
    1730       15730 :                 gf_bs_write_int(bs, 1, 1); // marker bit
    1731       15730 :                 t = ((cts >> 15) & 0x7fff);
    1732       15730 :                 gf_bs_write_long_int(bs, t, 15);
    1733       15730 :                 gf_bs_write_int(bs, 1, 1); // marker bit
    1734       15730 :                 t = cts & 0x7fff;
    1735       15730 :                 gf_bs_write_long_int(bs, t, 15);
    1736       15730 :                 gf_bs_write_int(bs, 1, 1); // marker bit
    1737             :         }
    1738             : 
    1739       15827 :         if (use_dts) {
    1740        1712 :                 gf_bs_write_int(bs, 0x1, 4); // reserved '0001'
    1741        1712 :                 t = ((dts >> 30) & 0x7);
    1742        1712 :                 gf_bs_write_long_int(bs, t, 3);
    1743        1712 :                 gf_bs_write_int(bs, 1, 1); // marker bit
    1744        1712 :                 t = ((dts >> 15) & 0x7fff);
    1745        1712 :                 gf_bs_write_long_int(bs, t, 15);
    1746        1712 :                 gf_bs_write_int(bs, 1, 1); // marker bit
    1747        1712 :                 t = dts & 0x7fff;
    1748        1712 :                 gf_bs_write_long_int(bs, t, 15);
    1749        1712 :                 gf_bs_write_int(bs, 1, 1); // marker bit
    1750             :         }
    1751       15827 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Adding PES header at PCR "LLD" - has PTS %d ("LLU") - has DTS %d ("LLU") - Payload length %d\n", stream->pid, gf_m2ts_get_pcr(stream)/300, use_pts, cts, use_dts, dts, pes_len));
    1752             : 
    1753       15827 :         return pes_len+4; // 4 = start code + stream_id
    1754             : }
    1755             : 
    1756      118568 : void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, char *packet)
    1757             : {
    1758             :         GF_BitStream *bs;
    1759             :         Bool needs_pcr, first_pass;
    1760             :         u32 adaptation_field_control, payload_length, payload_to_copy, padding_length, hdr_len, pos, copy_next;
    1761             : 
    1762             :         assert(stream->pid);
    1763      118568 :         bs = stream->program->mux->pck_bs;
    1764      118568 :         gf_bs_reassign_buffer(bs, packet, 188);
    1765             : 
    1766      118568 :         if (stream->pcr_only_mode) {
    1767             :                 payload_length = 184 - 8;
    1768             :                 needs_pcr = GF_TRUE;
    1769             :                 adaptation_field_control = GF_M2TS_ADAPTATION_ONLY;
    1770             :                 hdr_len = 0;
    1771             :         } else {
    1772             :                 hdr_len = gf_m2ts_stream_get_pes_header_length(stream);
    1773             : 
    1774             :                 /*we may need two pass in case we first compute hdr len and TS payload size by considering
    1775             :                 we concatenate next au start in this PES but finally couldn't do it when computing PES len
    1776             :                 and AU alignment constraint of the stream*/
    1777             :                 first_pass = GF_TRUE;
    1778             :                 while (1) {
    1779      118398 :                         if (hdr_len) {
    1780       15853 :                                 if (first_pass)
    1781       15827 :                                         gf_m2ts_stream_update_data_following(stream);
    1782             :                                 hdr_len = gf_m2ts_stream_get_pes_header_length(stream);
    1783             :                         }
    1784             : 
    1785             :                         adaptation_field_control = GF_M2TS_ADAPTATION_NONE;
    1786      118372 :                         payload_length = 184 - hdr_len;
    1787             :                         needs_pcr = GF_FALSE;
    1788             : 
    1789      118372 :                         if (stream == stream->program->pcr) {
    1790      107512 :                                 if (hdr_len)
    1791             :                                         needs_pcr = GF_TRUE;
    1792             :                                 /*if we forced inserting PAT/PMT before new RAP, also insert PCR here*/
    1793      107512 :                                 if (stream->program->mux->force_pat_pmt_state == GF_SEG_BOUNDARY_FORCE_PCR) {
    1794         125 :                                         stream->program->mux->force_pat_pmt_state = GF_SEG_BOUNDARY_NONE;
    1795             :                                         needs_pcr = GF_TRUE;
    1796             :                                 }
    1797             : 
    1798      107387 :                                 if (!needs_pcr && (stream->program->mux->real_time || stream->program->mux->fixed_rate) ) {
    1799             :                                         u64 clock;
    1800             :                                         u32 diff;
    1801         214 :                                         if (stream->program->mux->fixed_rate) {
    1802             :                                                 //check if PCR, if send at next packet, exceeds requested PCR update time
    1803         214 :                                                 clock = 1 + stream->program->mux->tot_pck_sent - stream->program->nb_pck_last_pcr;
    1804         214 :                                                 clock *= 1504*1000000;
    1805         214 :                                                 clock /= stream->program->mux->bit_rate;
    1806         214 :                                                 if (clock >= 500 + stream->program->mux->pcr_update_ms*1000) {
    1807             :                                                         needs_pcr = GF_TRUE;
    1808             :                                                 }
    1809             :                                         }
    1810             : 
    1811         214 :                                         if (!needs_pcr && stream->program->mux->real_time) {
    1812           0 :                                                 clock = gf_sys_clock_high_res();
    1813           0 :                                                 diff = (u32) (clock - stream->program->sys_clock_at_last_pcr);
    1814             : 
    1815           0 :                                                 if (diff >= 100 + stream->program->mux->pcr_update_ms*1000) {
    1816             :                                                         needs_pcr = GF_TRUE;
    1817             :                                                 }
    1818             :                                         }
    1819             :                                 }
    1820             :                         }
    1821             : 
    1822      107512 :                         if (needs_pcr) {
    1823             :                                 /*AF headers + PCR*/
    1824       10475 :                                 payload_length -= 8;
    1825             :                                 adaptation_field_control = GF_M2TS_ADAPTATION_AND_PAYLOAD;
    1826             :                         }
    1827             :                         //af descriptors are only inserted at the start of the pes for the time being
    1828      118372 :                         if (hdr_len && stream->curr_pck.mpeg2_af_descriptors) {
    1829         676 :                                 if (adaptation_field_control == GF_M2TS_ADAPTATION_NONE) {
    1830         330 :                                         payload_length -= 2; //AF header but no PCR
    1831             :                                         adaptation_field_control = GF_M2TS_ADAPTATION_AND_PAYLOAD;
    1832             :                                 }
    1833         676 :                                 payload_length -= 2 + stream->curr_pck.mpeg2_af_descriptors_size; //AF extension field and AF descriptor
    1834             :                         }
    1835             : 
    1836      118372 :                         if (hdr_len) {
    1837             :                                 assert(!stream->pes_data_remain);
    1838       15853 :                                 if (! gf_m2ts_stream_compute_pes_length(stream, payload_length)) {
    1839             :                                         first_pass = GF_FALSE;
    1840          26 :                                         continue;
    1841             :                                 }
    1842             : 
    1843             :                                 assert(stream->pes_data_remain==stream->pes_data_len);
    1844             :                         }
    1845             :                         break;
    1846             :                 }
    1847             :         }
    1848             : 
    1849      118568 :         copy_next = stream->copy_from_next_packets;
    1850      118568 :         payload_to_copy = stream->curr_pck.data_len - stream->pck_offset;
    1851             :         /*end of PES packet*/
    1852      118568 :         if (payload_to_copy >= stream->pes_data_remain) {
    1853             :                 payload_to_copy = stream->pes_data_remain;
    1854             :                 copy_next = 0;
    1855             :         }
    1856             : 
    1857             : 
    1858             :         /*packet exceed payload length*/
    1859      118568 :         if (payload_to_copy >= payload_length) {
    1860             :                 padding_length = 0;
    1861             :                 payload_to_copy = payload_length;
    1862             :         }
    1863             :         /*packet + next packet exceed payload length*/
    1864       19914 :         else if (payload_to_copy + copy_next >= payload_length) {
    1865             :                 padding_length = 0;
    1866             :         }
    1867             :         /*packet + next packet less than payload length - pad */
    1868             :         else {
    1869             :                 /*AF headers*/
    1870       12017 :                 if (!needs_pcr) {
    1871       10717 :                         if (adaptation_field_control == GF_M2TS_ADAPTATION_NONE) {
    1872       10715 :                                 payload_length -= 2;
    1873             :                                 adaptation_field_control = GF_M2TS_ADAPTATION_AND_PAYLOAD;
    1874             :                         }
    1875             :                 }
    1876             :                 /*cannot add adaptation field for this TS packet with this payload, we need to split in 2 TS packets*/
    1877       12017 :                 if (payload_length < payload_to_copy + copy_next) {
    1878             :                         padding_length = 10;
    1879          30 :                         payload_length -= padding_length;
    1880          30 :                         if (payload_to_copy > payload_length)
    1881             :                                 payload_to_copy = payload_length;
    1882             :                 } else {
    1883       11987 :                         padding_length = payload_length - payload_to_copy - copy_next;
    1884       11987 :                         payload_length -= padding_length;
    1885             :                 }
    1886             :         }
    1887             : 
    1888             : #ifndef GPAC_DISABLE_LOG
    1889      118568 :         if (hdr_len && gf_log_tool_level_on(GF_LOG_CONTAINER, GF_LOG_DEBUG) ) {
    1890           0 :                 u64 pcr = (s64) gf_m2ts_get_pcr(stream)/300;
    1891           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Start sending PES: PID %d - %d bytes - DTS "LLD" PCR "LLD" (diff %d) - stream time %d:%09d - mux time %d:%09d (%d us ahead of mux time)\n",
    1892             :                                                         stream->pid, stream->curr_pck.data_len, stream->curr_pck.dts, pcr, (s64) stream->curr_pck.dts - (s64) pcr,
    1893             :                                                         stream->time.sec, stream->time.nanosec, stream->program->mux->time.sec, stream->program->mux->time.nanosec,
    1894             :                                                         gf_m2ts_time_diff_us(&stream->program->mux->time, &stream->time)
    1895             :                                                        ));
    1896             :         }
    1897             : #endif
    1898             : 
    1899             :         //CC field shall not be incremented for if adaptation field only, rewind counter
    1900      118568 :         if (adaptation_field_control == GF_M2TS_ADAPTATION_ONLY) {
    1901         222 :                 if (!stream->continuity_counter) stream->continuity_counter=15;
    1902         143 :                 else stream->continuity_counter--;
    1903             :         }
    1904             : 
    1905      118568 :         gf_bs_write_int(bs,     0x47, 8); // sync byte
    1906      118568 :         gf_bs_write_int(bs,     0, 1);    // error indicator
    1907      118568 :         gf_bs_write_int(bs,     hdr_len ? 1 : 0, 1); // start ind
    1908      118568 :         gf_bs_write_int(bs,     0, 1);    // transport priority
    1909      118568 :         gf_bs_write_int(bs,     stream->pid, 13); // pid
    1910      118568 :         gf_bs_write_int(bs,     0, 2);    // scrambling
    1911      118568 :         gf_bs_write_int(bs,     adaptation_field_control, 2);    // we do not use adaptation field for sections
    1912      118568 :         gf_bs_write_int(bs,     stream->continuity_counter, 4);   // continuity counter
    1913             : 
    1914      118568 :         if (stream->continuity_counter < 15) stream->continuity_counter++;
    1915        7459 :         else stream->continuity_counter=0;
    1916             : 
    1917      118568 :         if (adaptation_field_control != GF_M2TS_ADAPTATION_NONE) {
    1918             :                 Bool is_rap = GF_FALSE;
    1919             :                 u64 pcr = 0;
    1920       21720 :                 if (needs_pcr) {
    1921       10675 :                         u64 now = gf_sys_clock_high_res();
    1922       10675 :                         pcr = gf_m2ts_get_pcr(stream);
    1923             : 
    1924       10675 :                         if (stream->program->mux->real_time || stream->program->mux->fixed_rate) {
    1925             :                                 u64 clock;
    1926         173 :                                 clock = stream->program->mux->tot_pck_sent - stream->program->nb_pck_last_pcr;
    1927         173 :                                 clock *= 1504000000;
    1928         173 :                                 clock /= stream->program->mux->bit_rate;
    1929             : 
    1930             :                                 //allow 2 ms drift
    1931         173 :                                 if (clock > 2000 + stream->program->mux->pcr_update_ms*1000) {
    1932           0 :                                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] PCR sent %d us later than requested PCR send rate %d ms\n", (s32) (clock - stream->program->mux->pcr_update_ms*1000), stream->program->mux->pcr_update_ms ));
    1933             :                                 }
    1934             : 
    1935         173 :                                 if (stream->program->mux->real_time) {
    1936           0 :                                         u32 diff = (s32) (now - stream->program->sys_clock_at_last_pcr);
    1937             :                                         //since we currently only send the PCR when an AU is sent, it may happen that we exceed PCR the refresh rate depending in the target bitrate and frame rate.
    1938             :                                         //we only throw a warning when twiice the PCR refresh is exceeded
    1939           0 :                                         if (diff > 5000 + 2*stream->program->mux->pcr_update_ms*1000 ) {
    1940           0 :                                                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sending PCR %d us too late (PCR send rate %d ms)\n", (u32) (diff - stream->program->mux->pcr_update_ms*1000), stream->program->mux->pcr_update_ms ));
    1941             :                                         }
    1942             :                                 }
    1943             :                         }
    1944             : 
    1945       10675 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Inserted PCR "LLD" (%d @90kHz) at mux time %d:%09d\n", pcr, (u32) (pcr/300), stream->program->mux->time.sec, stream->program->mux->time.nanosec ));
    1946       10675 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] PCR diff to STB in ms %d - sys clock diff in ms %d - DTS diff %d\n", (u32) (pcr - stream->program->last_pcr) / 27000, now - stream->program->sys_clock_at_last_pcr, (stream->curr_pck.dts - stream->program->last_dts)/90));
    1947             : 
    1948       10675 :                         stream->program->sys_clock_at_last_pcr = now;
    1949       10675 :                         stream->program->last_dts = stream->curr_pck.dts;
    1950       10675 :                         stream->program->nb_pck_last_pcr = stream->program->mux->tot_pck_sent;
    1951             :                 }
    1952       21720 :                 is_rap = (hdr_len && (stream->curr_pck.sap_type) ) ? GF_TRUE : GF_FALSE;
    1953       21720 :                 gf_m2ts_add_adaptation(stream->program, bs, stream->pid, needs_pcr, pcr, is_rap, padding_length, hdr_len ? stream->curr_pck.mpeg2_af_descriptors : NULL, hdr_len ? stream->curr_pck.mpeg2_af_descriptors_size : 0, stream->set_initial_disc);
    1954       21720 :                 stream->set_initial_disc = GF_FALSE;
    1955             : 
    1956       21720 :                 if (stream->curr_pck.mpeg2_af_descriptors) {
    1957         676 :                         gf_free(stream->curr_pck.mpeg2_af_descriptors);
    1958         676 :                         stream->curr_pck.mpeg2_af_descriptors = NULL;
    1959         676 :                         stream->curr_pck.mpeg2_af_descriptors_size = 0;
    1960             :                 }
    1961             : 
    1962       21720 :                 if (padding_length)
    1963       11982 :                         stream->program->mux->tot_pes_pad_bytes += padding_length;
    1964             :         }
    1965      118568 :         stream->pck_sap_type = 0;
    1966      118568 :         stream->pck_sap_time = 0;
    1967      118568 :         if (hdr_len) {
    1968       15827 :                 gf_m2ts_stream_add_pes_header(bs, stream);
    1969       15827 :                 if (stream->curr_pck.sap_type) {
    1970        9113 :                         stream->pck_sap_type = 1;
    1971        9113 :                         stream->pck_sap_time = stream->curr_pck.cts;
    1972             :                 }
    1973             :         }
    1974             : 
    1975      118568 :         pos = (u32) gf_bs_get_position(bs);
    1976             : 
    1977      118568 :         if (adaptation_field_control == GF_M2TS_ADAPTATION_ONLY) {
    1978             :                 return;
    1979             :         }
    1980             : 
    1981             :         assert(stream->curr_pck.data_len - stream->pck_offset >= payload_to_copy);
    1982      118346 :         memcpy(packet+pos, stream->curr_pck.data + stream->pck_offset, payload_to_copy);
    1983      118346 :         stream->pck_offset += payload_to_copy;
    1984             :         assert(stream->pes_data_remain >= payload_to_copy);
    1985      118346 :         stream->pes_data_remain -= payload_to_copy;
    1986             : 
    1987             :         /*update stream time, including headers*/
    1988      118346 :         gf_m2ts_time_inc(&stream->time, 1504/*188*8*/, stream->program->mux->bit_rate);
    1989             : 
    1990      118346 :         if (stream->pck_offset == stream->curr_pck.data_len) {
    1991       39440 :                 u64 pcr = gf_m2ts_get_pcr(stream)/300;
    1992       19720 :                 if (stream->program->mux->real_time && !stream->program->mux->fixed_rate && gf_m2ts_time_less(&stream->time, &stream->program->mux->time) ) {
    1993           0 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sent PES TOO LATE: PID %d - DTS "LLD" - PCR "LLD" - stream time %d:%09d - mux time %d:%09d - current mux rate %d\n",
    1994             :                                                                stream->pid, stream->curr_pck.dts, pcr,
    1995             :                                                                stream->time.sec, stream->time.nanosec, stream->program->mux->time.sec, stream->program->mux->time.nanosec,
    1996             :                                                                stream->program->mux->bit_rate
    1997             :                                                               ));
    1998       19720 :                 } else if (stream->curr_pck.dts < pcr) {
    1999         503 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sent PES %d us TOO LATE: PID %d - DTS "LLD" - size %d\n\tPCR "LLD" - stream time %d:%09d - mux time %d:%09d \n",
    2000             :                                 (pcr - stream->curr_pck.dts)*100/9, stream->pid, stream->curr_pck.dts, stream->curr_pck.data_len, pcr,
    2001             :                                 stream->time.sec, stream->time.nanosec, stream->program->mux->time.sec, stream->program->mux->time.nanosec
    2002             :                                                                  ));
    2003       19217 :                 } else if (stream->curr_pck.cts < pcr) {
    2004           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sent PES %d us TOO LATE: PID %d - DTS "LLD" - size %d\n\tPCR "LLD" - stream time %d:%09d - mux time %d:%09d \n",
    2005             :                                 pcr - stream->curr_pck.dts, stream->pid, stream->curr_pck.dts, stream->curr_pck.data_len, pcr,
    2006             :                                 stream->time.sec, stream->time.nanosec, stream->program->mux->time.sec, stream->program->mux->time.nanosec
    2007             :                                                                  ));
    2008             :                 } else {
    2009       19217 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sent PES: PID %d - DTS "LLD" - PCR "LLD" - stream time %d:%09d - mux time %d:%09d \n",
    2010             :                                                                stream->pid, stream->curr_pck.dts, pcr,
    2011             :                                                                stream->time.sec, stream->time.nanosec, stream->program->mux->time.sec, stream->program->mux->time.nanosec
    2012             :                                                               ));
    2013             : 
    2014             :                 }
    2015             : 
    2016             :                 /*PES has been sent, discard internal buffer*/
    2017       19720 :                 if (stream->discard_data) gf_free(stream->curr_pck.data);
    2018       19720 :                 stream->curr_pck.data = NULL;
    2019       19720 :                 stream->curr_pck.data_len = 0;
    2020       19720 :                 if (stream->curr_pck.mpeg2_af_descriptors) gf_free(stream->curr_pck.mpeg2_af_descriptors);
    2021       19720 :                 stream->curr_pck.mpeg2_af_descriptors = NULL;
    2022       19720 :                 stream->curr_pck.mpeg2_af_descriptors_size = 0;
    2023       19720 :                 stream->pck_offset = 0;
    2024             : 
    2025             : //#ifndef GPAC_DISABLE_LOG
    2026             : #if 0
    2027             :                 if (gf_m2ts_time_less(&stream->program->mux->time, &stream->time) ) {
    2028             :                         s32 drift = gf_m2ts_time_diff_us(&stream->program->mux->time, &stream->time);
    2029             :                         GF_LOG( (drift>1000) ? GF_LOG_WARNING : GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] PES PID %d sent %d us too late\n", stream->pid, drift) );
    2030             :                 }
    2031             : #endif
    2032             : 
    2033             :                 /*copy over from next PES to fill this TS packet*/
    2034       19720 :                 if (stream->copy_from_next_packets) {
    2035        8122 :                         pos += payload_to_copy;
    2036        8122 :                         copy_next = payload_length - payload_to_copy;
    2037             :                         /*we might need a more than one*/
    2038       16365 :                         while (stream->pes_data_remain) {
    2039             :                                 u32 remain = 0;
    2040        8029 :                                 Bool res = stream->process(stream->program->mux, stream);
    2041        8029 :                                 if (!res) {
    2042           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Not enough data to fill current PES (PID %d) - filling with 0xFF\n", stream->pid) );
    2043           0 :                                         memset(packet+pos, 0xFF, copy_next);
    2044             : 
    2045           0 :                                         if (stream->copy_from_next_packets > copy_next) {
    2046           0 :                                                 stream->copy_from_next_packets -= copy_next;
    2047             :                                         } else {
    2048           0 :                                                 stream->copy_from_next_packets = 0;
    2049             :                                         }
    2050             :                                         break;
    2051             :                                 }
    2052        8029 :                                 if (copy_next > stream->curr_pck.data_len) {
    2053         121 :                                         remain = copy_next - stream->curr_pck.data_len;
    2054             :                                         copy_next = stream->curr_pck.data_len;
    2055             :                                 }
    2056             : 
    2057        8029 :                                 memcpy(packet+pos, stream->curr_pck.data + stream->pck_offset, copy_next);
    2058        8029 :                                 stream->pck_offset += copy_next;
    2059             :                                 assert(stream->pes_data_remain >= copy_next);
    2060        8029 :                                 stream->pes_data_remain -= copy_next;
    2061             : 
    2062        8029 :                                 if (stream->copy_from_next_packets > copy_next) {
    2063        7921 :                                         stream->copy_from_next_packets -= copy_next;
    2064             :                                 } else {
    2065         108 :                                         stream->copy_from_next_packets = 0;
    2066             :                                 }
    2067             : 
    2068        8029 :                                 if (stream->pck_offset == stream->curr_pck.data_len) {
    2069             :                                         assert(!remain || (remain>=stream->min_bytes_copy_from_next));
    2070             :                                         /*PES has been sent, discard internal buffer*/
    2071         130 :                                         if (stream->discard_data) gf_free(stream->curr_pck.data);
    2072         130 :                                         stream->curr_pck.data = NULL;
    2073         130 :                                         stream->curr_pck.data_len = 0;
    2074         130 :                                         if (stream->curr_pck.mpeg2_af_descriptors) gf_free(stream->curr_pck.mpeg2_af_descriptors);
    2075         130 :                                         stream->curr_pck.mpeg2_af_descriptors = NULL;
    2076         130 :                                         stream->curr_pck.mpeg2_af_descriptors_size = 0;
    2077         130 :                                         stream->pck_offset = 0;
    2078             :                                 }
    2079        8029 :                                 if (!remain) break;
    2080         121 :                                 pos += copy_next;
    2081             :                                 copy_next = remain;
    2082             :                         }
    2083             :                 }
    2084       11598 :                 else if (stream->program->mux->force_pat_pmt_state==GF_SEG_BOUNDARY_START) {
    2085           0 :                         stream->program->mux->force_pat = GF_TRUE;
    2086             :                 }
    2087             :         }
    2088      118346 :         stream->bytes_since_last_time += 188;
    2089             : }
    2090             : 
    2091             : 
    2092         124 : GF_M2TS_Mux_Stream *gf_m2ts_stream_new(u32 pid) {
    2093             :         GF_M2TS_Mux_Stream *stream;
    2094             : 
    2095         124 :         GF_SAFEALLOC(stream, GF_M2TS_Mux_Stream);
    2096         124 :         if (!stream) {
    2097           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: fail to allocate\n", pid));
    2098             :                 return NULL;
    2099             :         }
    2100         124 :         stream->pid = pid;
    2101         124 :         stream->process = gf_m2ts_stream_process_pes;
    2102             : 
    2103         124 :         return stream;
    2104             : }
    2105             : 
    2106       19852 : GF_Err gf_m2ts_output_ctrl(GF_ESInterface *_self, u32 ctrl_type, void *param)
    2107             : {
    2108             :         GF_ESIPacket *esi_pck;
    2109             : 
    2110       19852 :         GF_M2TS_Mux_Stream *stream = (GF_M2TS_Mux_Stream *)_self->output_udta;
    2111       19852 :         switch (ctrl_type) {
    2112       19852 :         case GF_ESI_OUTPUT_DATA_DISPATCH:
    2113             :                 esi_pck = (GF_ESIPacket *)param;
    2114             : 
    2115       19852 :                 if (stream->force_new || (esi_pck->flags & GF_ESI_DATA_AU_START)) {
    2116       19852 :                         if (stream->pck_reassembler) {
    2117           0 :                                 if (stream->mx) gf_mx_p(stream->mx);
    2118           0 :                                 if (!stream->pck_first) {
    2119           0 :                                         stream->pck_first = stream->pck_last = stream->pck_reassembler;
    2120             :                                 } else {
    2121           0 :                                         stream->pck_last->next = stream->pck_reassembler;
    2122           0 :                                         stream->pck_last = stream->pck_reassembler;
    2123             :                                 }
    2124           0 :                                 if (stream->mx) gf_mx_v(stream->mx);
    2125           0 :                                 stream->pck_reassembler = NULL;
    2126             :                         }
    2127             :                 }
    2128       19852 :                 if (!stream->pck_reassembler) {
    2129       19852 :                         GF_SAFEALLOC(stream->pck_reassembler, GF_M2TS_Packet);
    2130       19852 :                         if (!stream->pck_reassembler) {
    2131           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: fail to allocate packet reassembler\n", stream->pid));
    2132             :                                 return GF_OUT_OF_MEM;
    2133             :                         }
    2134             : 
    2135       19852 :                         stream->pck_reassembler->cts = esi_pck->cts;
    2136       19852 :                         stream->pck_reassembler->dts = esi_pck->dts;
    2137       19852 :                         stream->pck_reassembler->duration = esi_pck->duration;
    2138       19852 :                         if (esi_pck->mpeg2_af_descriptors) {
    2139         676 :                                 stream->pck_reassembler->mpeg2_af_descriptors = (char*)gf_realloc(stream->pck_reassembler->mpeg2_af_descriptors, sizeof(u8)* (stream->pck_reassembler->mpeg2_af_descriptors_size + esi_pck->mpeg2_af_descriptors_size) );
    2140         676 :                                 memcpy(stream->pck_reassembler->mpeg2_af_descriptors + stream->pck_reassembler->mpeg2_af_descriptors_size, esi_pck->mpeg2_af_descriptors, sizeof(u8)* esi_pck->mpeg2_af_descriptors_size );
    2141         676 :                                 stream->pck_reassembler->mpeg2_af_descriptors_size += esi_pck->mpeg2_af_descriptors_size;
    2142             :                         }
    2143             :                 }
    2144             : 
    2145       19852 :                 stream->force_new = (esi_pck->flags & GF_ESI_DATA_AU_END) ? GF_TRUE : GF_FALSE;
    2146             : 
    2147       19852 :                 stream->pck_reassembler->data = (char*)gf_realloc(stream->pck_reassembler->data , sizeof(char)*(stream->pck_reassembler->data_len+esi_pck->data_len) );
    2148       19852 :                 if (esi_pck->data_len)
    2149       19841 :                         memcpy(stream->pck_reassembler->data + stream->pck_reassembler->data_len, esi_pck->data, esi_pck->data_len);
    2150       19852 :                 stream->pck_reassembler->data_len += esi_pck->data_len;
    2151             : 
    2152       19852 :                 stream->pck_reassembler->flags |= esi_pck->flags;
    2153       19852 :                 if (esi_pck->sap_type) stream->pck_reassembler->sap_type = esi_pck->sap_type;
    2154       19852 :                 if (stream->force_new) {
    2155       19852 :                         if (stream->mx) gf_mx_p(stream->mx);
    2156       19852 :                         if (!stream->pck_first) {
    2157       11621 :                                 stream->pck_first = stream->pck_last = stream->pck_reassembler;
    2158             :                         } else {
    2159        8231 :                                 stream->pck_last->next = stream->pck_reassembler;
    2160        8231 :                                 stream->pck_last = stream->pck_reassembler;
    2161             :                         }
    2162       19852 :                         if (stream->mx) gf_mx_v(stream->mx);
    2163       19852 :                         stream->pck_reassembler = NULL;
    2164             :                 }
    2165             :                 break;
    2166             :         }
    2167             :         return GF_OK;
    2168             : }
    2169             : 
    2170           2 : static void gf_m2ts_stream_set_default_slconfig(GF_M2TS_Mux_Stream *stream)
    2171             : {
    2172           2 :         if (!stream->ifce->sl_config) {
    2173           2 :                 stream->ifce->sl_config = (GF_SLConfig *)gf_odf_desc_new(GF_ODF_SLC_TAG);
    2174           2 :                 stream->ifce->sl_config->useAccessUnitStartFlag = 1;
    2175           2 :                 stream->ifce->sl_config->useAccessUnitEndFlag = 1;
    2176           2 :                 stream->ifce->sl_config->useRandomAccessPointFlag = 1;
    2177           2 :                 stream->ifce->sl_config->useTimestampsFlag = 1;
    2178             :         }
    2179           2 : }
    2180             : 
    2181             : static s32 gf_m2ts_find_stream(GF_M2TS_Mux_Program *program, u32 pid, u32 stream_id, GF_M2TS_Mux_Stream **out_stream)
    2182             : {
    2183             :         s32 i=0;
    2184             :         GF_M2TS_Mux_Stream *st = program->streams;
    2185             :         if (out_stream) *out_stream = NULL;
    2186           3 :         while (st) {
    2187           1 :                 if (pid && (st->pid == pid)) {
    2188             :                         if (out_stream) *out_stream = st;
    2189             :                         return i;
    2190             :                 }
    2191           1 :                 if (stream_id && (st->ifce->stream_id == stream_id)) {
    2192             :                         if (out_stream) *out_stream = st;
    2193             :                         return i;
    2194             :                 }
    2195           1 :                 st = st->next;
    2196           1 :                 i++;
    2197             :         }
    2198             :         return -1;
    2199             : }
    2200             : 
    2201             : 
    2202           1 : static void gf_m2ts_stream_add_hierarchy_descriptor(GF_M2TS_Mux_Stream *stream)
    2203             : {
    2204             :         GF_M2TSDescriptor *desc;
    2205             :         GF_BitStream *bs;
    2206             :         u32 data_len;
    2207           1 :         if (!stream || !stream->program || !stream->program->pmt) return;
    2208             : 
    2209           1 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    2210             :         /*reserved*/
    2211           1 :         gf_bs_write_int(bs, 1, 1);
    2212             :         /*temporal_scalability_flag: use the reserved value*/
    2213           1 :         gf_bs_write_int(bs, 1, 1);
    2214             :         /*spatial_scalability_flag: use the reserved value*/
    2215           1 :         gf_bs_write_int(bs, 1, 1);
    2216             :         /*quality_scalability_flag: use the reserved value*/
    2217           1 :         gf_bs_write_int(bs, 1, 1);
    2218             :         /*hierarchy_type: use the rerserved value*/
    2219           1 :         gf_bs_write_int(bs, 0, 4);
    2220             :         /*reserved*/
    2221           1 :         gf_bs_write_int(bs, 3, 2);
    2222             :         /*hierarchy_layer_index*/
    2223           2 :         gf_bs_write_int(bs, gf_m2ts_find_stream(stream->program, stream->pid, 0, NULL), 6);
    2224             :         /*tref_present_flag = 1 : NOT PRESENT*/
    2225           1 :         gf_bs_write_int(bs, 1, 1);
    2226             :         /*reserved*/
    2227           1 :         gf_bs_write_int(bs, 1, 1);
    2228             :         /*hierarchy_embedded_layer_index*/
    2229           2 :         gf_bs_write_int(bs, gf_m2ts_find_stream(stream->program, 0, stream->ifce->depends_on_stream, NULL), 6);
    2230             :         /*reserved*/
    2231           1 :         gf_bs_write_int(bs, 3, 2);
    2232             :         /*hierarchy_channel*/
    2233           1 :         gf_bs_write_int(bs, stream->ifce->stream_id, 6);
    2234             : 
    2235           1 :         GF_SAFEALLOC(desc, GF_M2TSDescriptor);
    2236           1 :         if (!desc) return;
    2237             : 
    2238           1 :         desc->tag = (u8) GF_M2TS_HIERARCHY_DESCRIPTOR;
    2239           1 :         gf_bs_get_content(bs, &desc->data, &data_len);
    2240           1 :         gf_bs_del(bs);
    2241           1 :         desc->data_len = (u8) data_len;
    2242           1 :         gf_list_add(stream->loop_descriptors, desc);
    2243             : }
    2244             : 
    2245           2 : static void gf_m2ts_stream_add_metadata_pointer_descriptor(GF_M2TS_Mux_Program *program)
    2246             : {
    2247             :         GF_M2TSDescriptor *desc;
    2248             :         GF_BitStream *bs;
    2249             :         u32 data_len;
    2250           2 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    2251           2 :         gf_bs_write_u16(bs, 0xFFFF);
    2252           2 :         gf_bs_write_u32(bs, GF_M2TS_META_ID3);
    2253           2 :         gf_bs_write_u8(bs, 0xFF);
    2254           2 :         gf_bs_write_u32(bs, GF_M2TS_META_ID3);
    2255           2 :         gf_bs_write_u8(bs, 0); /* service id */
    2256           2 :         gf_bs_write_int(bs, 0, 1); /* locator */
    2257           2 :         gf_bs_write_int(bs, 0, 2); /* carriage flags */
    2258           2 :         gf_bs_write_int(bs, 0x1F, 5); /* reserved */
    2259           2 :         gf_bs_write_u16(bs, program->number);
    2260           2 :         GF_SAFEALLOC(desc, GF_M2TSDescriptor);
    2261           2 :         if (!desc) return;
    2262             : 
    2263           2 :         desc->tag = (u8) GF_M2TS_METADATA_POINTER_DESCRIPTOR;
    2264           2 :         gf_bs_get_content(bs, &desc->data, &data_len);
    2265           2 :         gf_bs_del(bs);
    2266           2 :         desc->data_len = (u8) data_len;
    2267           2 :         gf_list_add(program->loop_descriptors, desc);
    2268             : }
    2269             : 
    2270           2 : static void gf_m2ts_stream_add_metadata_descriptor(GF_M2TS_Mux_Stream *stream)
    2271             : {
    2272             :         GF_M2TSDescriptor *desc;
    2273             :         GF_BitStream *bs;
    2274             :         u32 data_len;
    2275           2 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    2276           2 :         gf_bs_write_u16(bs, 0xFFFF);
    2277           2 :         gf_bs_write_u32(bs, GF_M2TS_META_ID3);
    2278           2 :         gf_bs_write_u8(bs, 0xFF);
    2279           2 :         gf_bs_write_u32(bs, GF_M2TS_META_ID3);
    2280           2 :         gf_bs_write_u8(bs, 0); /* service id */
    2281           2 :         gf_bs_write_int(bs, 0, 3); /* decoder config flags */
    2282           2 :         gf_bs_write_int(bs, 0, 1); /* dsmcc flag */
    2283           2 :         gf_bs_write_int(bs, 0xF, 4); /* reserved */
    2284           2 :         GF_SAFEALLOC(desc, GF_M2TSDescriptor);
    2285           2 :         if (!desc) return;
    2286             : 
    2287           2 :         desc->tag = (u8) GF_M2TS_METADATA_DESCRIPTOR;
    2288           2 :         gf_bs_get_content(bs, &desc->data, &data_len);
    2289           2 :         gf_bs_del(bs);
    2290           2 :         desc->data_len = (u8) data_len;
    2291           2 :         gf_list_add(stream->loop_descriptors, desc);
    2292             : }
    2293             : 
    2294             : GF_EXPORT
    2295          49 : u32 gf_m2ts_mux_program_get_pmt_pid(GF_M2TS_Mux_Program *prog)
    2296             : {
    2297          49 :         return prog->pmt ? prog->pmt->pid : 0;
    2298             : }
    2299             : 
    2300             : GF_EXPORT
    2301          49 : u32 gf_m2ts_mux_program_get_pcr_pid(GF_M2TS_Mux_Program *prog)
    2302             : {
    2303          49 :         return prog->pcr ? prog->pcr->pid : 0;
    2304             : }
    2305             : 
    2306             : GF_EXPORT
    2307          49 : u32 gf_m2ts_mux_program_get_stream_count(GF_M2TS_Mux_Program *prog)
    2308             : {
    2309          49 :         GF_M2TS_Mux_Stream *stream = prog->streams;
    2310             :         u32 count=0;
    2311         111 :         while (stream) {
    2312          13 :                 count++;
    2313          13 :                 stream = stream->next;
    2314             :         }
    2315          49 :         return count;
    2316             : }
    2317             : 
    2318             : GF_EXPORT
    2319          49 : GF_M2TS_Mux_Stream *gf_m2ts_program_stream_add(GF_M2TS_Mux_Program *program, struct __elementary_stream_ifce *ifce, u32 pid, Bool is_pcr, Bool force_pes, Bool needs_mutex)
    2320             : {
    2321             :         GF_M2TS_Mux_Stream *stream, *st;
    2322             : 
    2323          49 :         stream = gf_m2ts_stream_new(pid);
    2324          49 :         stream->ifce = ifce;
    2325          49 :         stream->pid = pid;
    2326          49 :         stream->program = program;
    2327          49 :         if (is_pcr) program->pcr = stream;
    2328          49 :         stream->loop_descriptors = gf_list_new();
    2329          49 :         stream->set_initial_disc = program->initial_disc_set;
    2330             : 
    2331          49 :         if (program->streams) {
    2332             :                 /*if PCR keep stream at the beginning*/
    2333          12 :                 if (is_pcr) {
    2334          11 :                         stream->next = program->streams;
    2335          11 :                         program->streams = stream;
    2336             :                 } else {
    2337             :                         st = program->streams;
    2338           1 :                         while (st->next) st = st->next;
    2339           1 :                         st->next = stream;
    2340             :                 }
    2341             :         } else {
    2342          37 :                 program->streams = stream;
    2343             :         }
    2344          49 :         if (program->pmt) program->pmt->table_needs_update = GF_TRUE;
    2345          49 :         stream->bit_rate = ifce->bit_rate;
    2346          49 :         stream->scheduling_priority = 1;
    2347             : 
    2348          49 :         stream->force_single_au = (stream->program->mux->au_pes_mode == GF_M2TS_PACK_ALL) ? GF_FALSE : GF_TRUE;
    2349             : 
    2350          49 :         switch (ifce->stream_type) {
    2351          23 :         case GF_STREAM_VISUAL:
    2352             :                 /*just pick first valid stream_id in visual range*/
    2353          23 :                 stream->mpeg2_stream_id = 0xE0;
    2354             :                 /*for video streams, prevent sending two frames start in one PES. This will
    2355             :                 introduce more overhead at very low bitrates where such cases happen, but will ensure proper timing
    2356             :                 of each frame*/
    2357          23 :                 stream->prevent_two_au_start_in_pes = GF_TRUE;
    2358          23 :                 switch (ifce->codecid) {
    2359           3 :                 case GF_CODECID_MPEG4_PART2:
    2360           3 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG4;
    2361           3 :                         break;
    2362          16 :                 case GF_CODECID_AVC:
    2363          16 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_H264;
    2364             :                         /*make sure we send AU delim NALU in same PES as first VCL NAL: 6 bytes (start code + 1 nal hdr + AU delim)
    2365             :                         + 4 byte start code + first nal header*/
    2366          16 :                         stream->min_bytes_copy_from_next = 11;
    2367          16 :                         break;
    2368           0 :                 case GF_CODECID_SVC:
    2369           0 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_SVC;
    2370             :                         /*make sure we send AU delim NALU in same PES as first VCL NAL: 6 bytes (start code + 1 nal hdr + AU delim)
    2371             :                         + 4 byte start code + first nal header*/
    2372           0 :                         stream->min_bytes_copy_from_next = 11;
    2373           0 :                         gf_m2ts_stream_add_hierarchy_descriptor(stream);
    2374           0 :                         break;
    2375           1 :                 case GF_CODECID_HEVC:
    2376           1 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_HEVC;
    2377             :                         //this is a bit crude and will need refinement
    2378           1 :                         if (ifce->depends_on_stream) {
    2379             :                                 GF_M2TS_Mux_Stream *base_st;
    2380           0 :                                 stream->mpeg2_stream_type = GF_M2TS_VIDEO_HEVC_TEMPORAL;
    2381           0 :                                 gf_m2ts_stream_add_hierarchy_descriptor(stream);
    2382           0 :                                 stream->force_single_au = GF_TRUE;
    2383           0 :                                 gf_m2ts_find_stream(program, 0, ifce->depends_on_stream, &base_st);
    2384           0 :                                 if (base_st) base_st->force_single_au = GF_TRUE;
    2385             :                         }
    2386             : 
    2387             :                         /*make sure we send AU delim NALU in same PES as first VCL NAL: 7 bytes (4 start code + 2 nal header + 1 AU delim)
    2388             :                         + 4 byte start code + first nal header*/
    2389           1 :                         stream->min_bytes_copy_from_next = 12;
    2390           1 :                         break;
    2391           1 :                 case GF_CODECID_LHVC:
    2392             :                         //FIXME - we need to check scalability type to see if we have MHVC, for now only use SHVC
    2393           1 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_SHVC;
    2394             :                         /*make sure we send AU delim NALU in same PES as first VCL NAL: 7 bytes (4 start code + 2 nal header + 1 AU delim)
    2395             :                         + 4 byte start code + first nal header*/
    2396           1 :                         stream->min_bytes_copy_from_next = 12;
    2397           1 :                         gf_m2ts_stream_add_hierarchy_descriptor(stream);
    2398             :                         //force by default with SHVC since we don't have any delimiter / layer yet
    2399           1 :                         stream->force_single_au = GF_TRUE;
    2400           1 :                         break;
    2401           1 :                 case GF_CODECID_MPEG1:
    2402           1 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG1;
    2403           1 :                         break;
    2404           0 :                 case GF_CODECID_MPEG2_SIMPLE:
    2405             :                 case GF_CODECID_MPEG2_MAIN:
    2406             :                 case GF_CODECID_MPEG2_SNR:
    2407             :                 case GF_CODECID_MPEG2_SPATIAL:
    2408             :                 case GF_CODECID_MPEG2_HIGH:
    2409             :                 case GF_CODECID_MPEG2_422:
    2410           0 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG2;
    2411           0 :                         break;
    2412             :                 /*JPEG/PNG carried in MPEG-4 PES*/
    2413           0 :                 case GF_CODECID_JPEG:
    2414             :                 case GF_CODECID_PNG:
    2415           0 :                         stream->mpeg2_stream_type = GF_M2TS_SYSTEMS_MPEG4_PES;
    2416           0 :                         stream->force_single_au = GF_TRUE;
    2417           0 :                         stream->mpeg2_stream_id = 0xFA;
    2418           0 :                         gf_m2ts_stream_set_default_slconfig(stream);
    2419           0 :                         break;
    2420           0 :                 case GF_CODECID_VVC:
    2421           0 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_VVC;
    2422             :                         /*make sure we send AU delim NALU in same PES as first VCL NAL: 7 bytes (4 start code + 2 nal header + 1 AU delim)
    2423             :                         + 4 byte start code + first nal header*/
    2424           0 :                         stream->min_bytes_copy_from_next = 12;
    2425           0 :                         break;
    2426           0 :                 case GF_CODECID_SMPTE_VC1:
    2427           0 :                         stream->mpeg2_stream_type = GF_M2TS_VIDEO_VC1;
    2428           0 :                         break;
    2429           1 :                 default:
    2430           1 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] Unsupported mpeg2-ts video type for codec %s, signaling as PES private using codec 4CC in registration descriptor\n", gf_codecid_name(ifce->codecid) ));
    2431             : 
    2432           1 :                         stream->mpeg2_stream_type = GF_M2TS_PRIVATE_DATA;
    2433           1 :                         stream->force_single_au = GF_TRUE;
    2434           1 :                         stream->force_reg_desc = GF_TRUE;
    2435           1 :                         break;
    2436             :                 }
    2437             :                 break;
    2438          22 :         case GF_STREAM_AUDIO:
    2439             :                 /*just pick first valid stream_id in audio range*/
    2440          22 :                 stream->mpeg2_stream_id = 0xC0;
    2441             :                 //override default packing for audio
    2442          22 :                 stream->force_single_au = (stream->program->mux->au_pes_mode == GF_M2TS_PACK_NONE) ? GF_TRUE : GF_FALSE;
    2443          22 :                 switch (ifce->codecid) {
    2444           0 :                 case GF_CODECID_MPEG_AUDIO:
    2445           0 :                         stream->mpeg2_stream_type = GF_M2TS_AUDIO_MPEG1;
    2446           0 :                         break;
    2447           1 :                 case GF_CODECID_MPEG2_PART3:
    2448           1 :                         stream->mpeg2_stream_type = GF_M2TS_AUDIO_MPEG2;
    2449           1 :                         break;
    2450          18 :                 case GF_CODECID_AAC_MPEG4:
    2451             :                 case GF_CODECID_AAC_MPEG2_MP:
    2452             :                 case GF_CODECID_AAC_MPEG2_LCP:
    2453             :                 case GF_CODECID_AAC_MPEG2_SSRP:
    2454          18 :                         if (ifce->caps & GF_ESI_AAC_USE_LATM)
    2455           0 :                                 stream->mpeg2_stream_type = GF_M2TS_AUDIO_LATM_AAC;
    2456             :                         else
    2457          18 :                                 stream->mpeg2_stream_type = GF_M2TS_AUDIO_AAC;
    2458             : 
    2459          18 :                         if (!ifce->repeat_rate) ifce->repeat_rate = 500;
    2460             :                         break;
    2461           2 :                 case GF_CODECID_AC3:
    2462           2 :                         stream->mpeg2_stream_type = GF_M2TS_AUDIO_AC3;
    2463           2 :                         break;
    2464           0 :                 case GF_CODECID_EAC3:
    2465           0 :                         stream->mpeg2_stream_type = GF_M2TS_AUDIO_EC3;
    2466           0 :                         break;
    2467           1 :                 default:
    2468           1 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] Unsupported mpeg2-ts audio type for codec %s, signaling as PES private using codec 4CC in registration descriptor\n", gf_codecid_name(ifce->codecid) ));
    2469           1 :                         stream->mpeg2_stream_type = GF_M2TS_PRIVATE_DATA;
    2470           1 :                         stream->force_single_au = GF_TRUE;
    2471           1 :                         stream->force_reg_desc = GF_TRUE;
    2472           1 :                         break;
    2473             :                 }
    2474             :                 break;
    2475           1 :         case GF_STREAM_OD:
    2476             :                 /*highest priority for OD streams as they are needed to process other streams*/
    2477           1 :                 stream->scheduling_priority = 20;
    2478           1 :                 stream->mpeg2_stream_id = 0xFA;
    2479           1 :                 stream->table_id = GF_M2TS_TABLE_ID_MPEG4_OD;
    2480           1 :                 gf_m2ts_stream_set_default_slconfig(stream);
    2481           1 :                 if (force_pes) {
    2482           0 :                         stream->mpeg2_stream_type = GF_M2TS_SYSTEMS_MPEG4_PES;
    2483           0 :                         stream->force_single_au = GF_TRUE;
    2484             :                 } else {
    2485           1 :                         stream->mpeg2_stream_type = GF_M2TS_SYSTEMS_MPEG4_SECTIONS;
    2486             :                 }
    2487             :                 break;
    2488           1 :         case GF_STREAM_SCENE:
    2489           1 :                 stream->mpeg2_stream_id = 0xFA;
    2490           1 :                 stream->table_id = GF_M2TS_TABLE_ID_MPEG4_BIFS;
    2491           1 :                 gf_m2ts_stream_set_default_slconfig(stream);
    2492             : 
    2493           1 :                 if (force_pes) {
    2494           0 :                         stream->mpeg2_stream_type = GF_M2TS_SYSTEMS_MPEG4_PES;
    2495           0 :                         stream->force_single_au = GF_TRUE;
    2496             :                 } else {
    2497           1 :                         stream->mpeg2_stream_type = GF_M2TS_SYSTEMS_MPEG4_SECTIONS;
    2498             :                 }
    2499             :                 break;
    2500           2 :         case GF_STREAM_TEXT:
    2501           2 :                 stream->mpeg2_stream_id = 0xBD;
    2502           2 :                 stream->mpeg2_stream_type = GF_M2TS_METADATA_PES;
    2503           2 :                 gf_m2ts_stream_add_metadata_pointer_descriptor(stream->program);
    2504           2 :                 gf_m2ts_stream_add_metadata_descriptor(stream);
    2505           2 :                 break;
    2506           0 :         default:
    2507           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] Unsupported codec %s, signaling as raw data\n", gf_codecid_name(ifce->codecid) ));
    2508           0 :                 stream->mpeg2_stream_id = 0xBD;
    2509           0 :                 stream->mpeg2_stream_type = GF_M2TS_METADATA_PES;
    2510           0 :                 break;
    2511             :         }
    2512             : 
    2513          49 :         if (! (ifce->caps & GF_ESI_STREAM_WITHOUT_MPEG4_SYSTEMS)) {
    2514             :                 /*override signaling for all streams except BIFS/OD, to use MPEG-4 PES*/
    2515          49 :                 if (program->mpeg4_signaling==GF_M2TS_MPEG4_SIGNALING_FULL) {
    2516           0 :                         if (stream->mpeg2_stream_type != GF_M2TS_SYSTEMS_MPEG4_SECTIONS) {
    2517           0 :                                 stream->mpeg2_stream_type = GF_M2TS_SYSTEMS_MPEG4_PES;
    2518           0 :                                 stream->force_single_au = GF_TRUE;
    2519           0 :                                 stream->mpeg2_stream_id = 0xFA;/*ISO/IEC14496-1_SL-packetized_stream*/
    2520           0 :                                 gf_m2ts_stream_set_default_slconfig(stream);
    2521             :                         }
    2522             :                 }
    2523             :         }
    2524             : 
    2525          49 :         stream->ifce->output_ctrl = gf_m2ts_output_ctrl;
    2526          49 :         stream->ifce->output_udta = stream;
    2527          49 :         if (needs_mutex)
    2528           0 :                 stream->mx = gf_mx_new("M2TS PID");
    2529             : 
    2530          49 :         if (ifce->timescale != 90000) {
    2531          42 :                 stream->ts_scale.num = 90000;
    2532          42 :                 stream->ts_scale.den = ifce->timescale;
    2533             :         }
    2534          49 :         return stream;
    2535             : }
    2536             : 
    2537             : #if 0 //unused
    2538             : GF_Err gf_m2ts_program_stream_update_ts_scale(GF_ESInterface *_self, u32 time_scale)
    2539             : {
    2540             :         GF_M2TS_Mux_Stream *stream = (GF_M2TS_Mux_Stream *)_self->output_udta;
    2541             :         if (!stream || !time_scale)
    2542             :                 return GF_BAD_PARAM;
    2543             : 
    2544             :         stream->ts_scale.num = 90000;
    2545             :         stream->ts_scale.den = time_scale;
    2546             :         return GF_OK;
    2547             : }
    2548             : #endif
    2549             : 
    2550             : GF_EXPORT
    2551          50 : GF_M2TS_Mux_Program *gf_m2ts_mux_program_find(GF_M2TS_Mux *muxer, u32 program_number)
    2552             : {
    2553          50 :         GF_M2TS_Mux_Program *program = muxer->programs;
    2554         100 :         while (program) {
    2555          13 :                 if (program->number == program_number) return program;
    2556           0 :                 program = program->next;
    2557             :         }
    2558             :         return NULL;
    2559             : }
    2560             : 
    2561             : 
    2562             : GF_EXPORT
    2563          37 : u32 gf_m2ts_mux_program_count(GF_M2TS_Mux *muxer)
    2564             : {
    2565             :         u32 num=0;
    2566          37 :         GF_M2TS_Mux_Program *program = muxer->programs;
    2567          74 :         while (program) {
    2568           0 :                 num++;
    2569           0 :                 program = program->next;
    2570             :         }
    2571          37 :         return num;
    2572             : }
    2573             : 
    2574             : GF_EXPORT
    2575          37 : GF_M2TS_Mux_Program *gf_m2ts_mux_program_add(GF_M2TS_Mux *muxer, u32 program_number, u32 pmt_pid, u32 pmt_refresh_rate, u64 pcr_offset, u32 mpeg4_signaling, u32 pmt_version, Bool initial_disc, u64 force_first_pts)
    2576             : {
    2577             :         GF_M2TS_Mux_Program *program;
    2578             : 
    2579          37 :         GF_SAFEALLOC(program, GF_M2TS_Mux_Program);
    2580          37 :         if (!program) return NULL;
    2581             : 
    2582          37 :         program->mux = muxer;
    2583          37 :         program->mpeg4_signaling = mpeg4_signaling;
    2584          37 :         program->pcr_offset = pcr_offset;
    2585          37 :         program->loop_descriptors = gf_list_new();
    2586             : 
    2587          37 :         program->number = program_number;
    2588          37 :         if (muxer->programs) {
    2589             :                 GF_M2TS_Mux_Program *p = muxer->programs;
    2590           0 :                 while (p->next) p = p->next;
    2591           0 :                 p->next = program;
    2592             :         } else {
    2593          37 :                 muxer->programs = program;
    2594             :         }
    2595          37 :         program->pmt = gf_m2ts_stream_new(pmt_pid);
    2596          37 :         program->pmt->program = program;
    2597          37 :         program->pmt->table_needs_update = GF_TRUE;
    2598          37 :         program->pmt->initial_version_number = pmt_version;
    2599          37 :         program->initial_disc_set = initial_disc;
    2600          37 :         program->pmt->set_initial_disc = initial_disc;
    2601          37 :         muxer->pat->table_needs_update = GF_TRUE;
    2602          37 :         program->pmt->process = gf_m2ts_stream_process_pmt;
    2603          37 :         program->force_first_pts = force_first_pts;
    2604          37 :         program->pmt->refresh_rate_ms = pmt_refresh_rate ? pmt_refresh_rate : (u32) -1;
    2605          37 :         return program;
    2606             : }
    2607             : 
    2608             : GF_EXPORT
    2609           1 : void gf_m2ts_mux_program_set_name(GF_M2TS_Mux_Program *program, const char *program_name, const char *provider_name)
    2610             : {
    2611           1 :         if (program->name) gf_free(program->name);
    2612           1 :         program->name = program_name ? gf_strdup(program_name) : NULL;
    2613             : 
    2614           1 :         if (program->provider) gf_free(program->provider);
    2615           1 :         program->provider = provider_name ? gf_strdup(provider_name) : NULL;
    2616             : 
    2617           1 :         if (program->mux->sdt) program->mux->sdt->table_needs_update = GF_TRUE;
    2618           1 : }
    2619             : 
    2620             : GF_EXPORT
    2621          37 : GF_M2TS_Mux *gf_m2ts_mux_new(u32 mux_rate, u32 pat_refresh_rate, Bool real_time)
    2622             : {
    2623             :         GF_M2TS_Mux *muxer;
    2624          37 :         GF_SAFEALLOC(muxer, GF_M2TS_Mux);
    2625          37 :         if (!muxer) return NULL;
    2626             : 
    2627          37 :         muxer->pat = gf_m2ts_stream_new(GF_M2TS_PID_PAT);
    2628          37 :         if (!muxer->pat) {
    2629           0 :                 gf_free(muxer);
    2630           0 :                 return NULL;
    2631             :         }
    2632          37 :         muxer->pat->process = gf_m2ts_stream_process_pat;
    2633          37 :         muxer->pat->refresh_rate_ms = pat_refresh_rate ? pat_refresh_rate : (u32) -1;
    2634          37 :         muxer->real_time = real_time;
    2635          37 :         muxer->bit_rate = mux_rate;
    2636          37 :         muxer->init_pcr_value = 0;
    2637          37 :         if (mux_rate) muxer->fixed_rate = GF_TRUE;
    2638             : 
    2639             :         /*format NULL packet*/
    2640          37 :         muxer->pck_bs = gf_bs_new(muxer->null_pck, 188, GF_BITSTREAM_WRITE);
    2641          37 :         gf_bs_write_int(muxer->pck_bs,       0x47, 8);
    2642          37 :         gf_bs_write_int(muxer->pck_bs,       0, 1);
    2643          37 :         gf_bs_write_int(muxer->pck_bs,       0, 1);
    2644          37 :         gf_bs_write_int(muxer->pck_bs,       0, 1);
    2645          37 :         gf_bs_write_int(muxer->pck_bs,       0x1FFF, 13);
    2646          37 :         gf_bs_write_int(muxer->pck_bs,       0, 2);
    2647          37 :         gf_bs_write_int(muxer->pck_bs,       1, 2);
    2648          37 :         gf_bs_write_int(muxer->pck_bs,       0, 4);
    2649             : 
    2650          37 :         gf_rand_init(GF_FALSE);
    2651          37 :         muxer->pcr_update_ms = 100;
    2652          37 :         return muxer;
    2653             : }
    2654             : 
    2655             : GF_EXPORT
    2656           1 : void gf_m2ts_mux_enable_sdt(GF_M2TS_Mux *mux, u32 refresh_rate_ms)
    2657             : {
    2658           1 :         if (!mux->sdt) {
    2659           1 :                 mux->sdt = gf_m2ts_stream_new(GF_M2TS_PID_SDT_BAT_ST);
    2660           1 :                 mux->sdt->process = gf_m2ts_stream_process_sdt;
    2661           1 :                 mux->sdt->refresh_rate_ms = refresh_rate_ms;
    2662             :         }
    2663           1 :         mux->sdt->table_needs_update = GF_TRUE;
    2664           1 :         return;
    2665             : }
    2666             : 
    2667             : 
    2668             : GF_EXPORT
    2669          37 : void gf_m2ts_mux_set_pcr_max_interval(GF_M2TS_Mux *muxer, u32 pcr_update_ms)
    2670             : {
    2671          37 :         if (muxer && (pcr_update_ms<=100)) muxer->pcr_update_ms = pcr_update_ms;
    2672          37 : }
    2673             : 
    2674         124 : void gf_m2ts_mux_stream_del(GF_M2TS_Mux_Stream *st)
    2675             : {
    2676         325 :         while (st->tables) {
    2677          77 :                 GF_M2TS_Mux_Table *tab = st->tables->next;
    2678         231 :                 while (st->tables->section) {
    2679          77 :                         GF_M2TS_Mux_Section *sec = st->tables->section->next;
    2680          77 :                         gf_free(st->tables->section->data);
    2681          77 :                         gf_free(st->tables->section);
    2682          77 :                         st->tables->section = sec;
    2683             :                 }
    2684          77 :                 gf_free(st->tables);
    2685          77 :                 st->tables = tab;
    2686             :         }
    2687         124 :         while (st->pck_first) {
    2688             :                 GF_M2TS_Packet *curr_pck = st->pck_first;
    2689           0 :                 st->pck_first = curr_pck->next;
    2690           0 :                 gf_free(curr_pck->data);
    2691           0 :                 gf_free(curr_pck);
    2692             :         }
    2693         124 :         if (st->curr_pck.data) gf_free(st->curr_pck.data);
    2694         124 :         if (st->curr_pck.mpeg2_af_descriptors) gf_free(st->curr_pck.mpeg2_af_descriptors);
    2695         124 :         if (st->mx) gf_mx_del(st->mx);
    2696         124 :         if (st->loop_descriptors) {
    2697          52 :                 while (gf_list_count(st->loop_descriptors) ) {
    2698           3 :                         GF_M2TSDescriptor *desc = (GF_M2TSDescriptor*)gf_list_last(st->loop_descriptors);
    2699           3 :                         gf_list_rem_last(st->loop_descriptors);
    2700           3 :                         if (desc->data) gf_free(desc->data);
    2701           3 :                         gf_free(desc);
    2702             :                 }
    2703          49 :                 gf_list_del(st->loop_descriptors);
    2704             :         }
    2705         124 :         gf_free(st);
    2706         124 : }
    2707             : 
    2708          37 : void gf_m2ts_mux_program_del(GF_M2TS_Mux_Program *prog)
    2709             : {
    2710          37 :         if (prog->iod) {
    2711           1 :                 gf_odf_desc_del(prog->iod);
    2712             :         }
    2713          86 :         while (prog->streams) {
    2714          49 :                 GF_M2TS_Mux_Stream *st = prog->streams->next;
    2715          49 :                 gf_m2ts_mux_stream_del(prog->streams);
    2716          49 :                 prog->streams = st;
    2717             :         }
    2718          37 :         if (prog->loop_descriptors) {
    2719          39 :                 while (gf_list_count(prog->loop_descriptors) ) {
    2720           2 :                         GF_M2TSDescriptor *desc = (GF_M2TSDescriptor*)gf_list_last(prog->loop_descriptors);
    2721           2 :                         gf_list_rem_last(prog->loop_descriptors);
    2722           2 :                         if (desc->data) gf_free(desc->data);
    2723           2 :                         gf_free(desc);
    2724             :                 }
    2725          37 :                 gf_list_del(prog->loop_descriptors);
    2726             :         }
    2727          37 :         gf_m2ts_mux_stream_del(prog->pmt);
    2728          37 :         if (prog->name) gf_free(prog->name);
    2729          37 :         if (prog->provider) gf_free(prog->provider);
    2730          37 :         gf_free(prog);
    2731          37 : }
    2732             : 
    2733             : GF_EXPORT
    2734           0 : void gf_m2ts_program_stream_remove(GF_M2TS_Mux_Stream *stream)
    2735             : {
    2736           0 :         GF_M2TS_Mux_Program *program = stream->program;
    2737           0 :         GF_M2TS_Mux_Stream *a_stream = program->streams;
    2738           0 :         if (a_stream==stream) {
    2739           0 :                 program->streams = stream->next;
    2740             :         } else {
    2741           0 :                 while (a_stream) {
    2742           0 :                         if (a_stream->next == stream) {
    2743           0 :                                 a_stream->next = stream->next;
    2744           0 :                                 break;
    2745             :                         }
    2746             :                         a_stream = a_stream->next;
    2747             :                 }
    2748             :         }
    2749           0 :         stream->next = NULL;
    2750           0 :         gf_m2ts_mux_stream_del(stream);
    2751           0 :         program->pmt->table_needs_update = GF_TRUE;
    2752           0 : }
    2753             : 
    2754             : GF_EXPORT
    2755          37 : void gf_m2ts_mux_del(GF_M2TS_Mux *mux)
    2756             : {
    2757         111 :         while (mux->programs) {
    2758          37 :                 GF_M2TS_Mux_Program *p = mux->programs->next;
    2759          37 :                 gf_m2ts_mux_program_del(mux->programs);
    2760          37 :                 mux->programs = p;
    2761             :         }
    2762          37 :         gf_m2ts_mux_stream_del(mux->pat);
    2763          37 :         if (mux->sdt) gf_m2ts_mux_stream_del(mux->sdt);
    2764          37 :         if (mux->pck_bs) gf_bs_del(mux->pck_bs);
    2765             : 
    2766          37 :         gf_free(mux);
    2767          37 : }
    2768             : 
    2769             : GF_EXPORT
    2770        6303 : void gf_m2ts_mux_update_config(GF_M2TS_Mux *mux, Bool reset_time)
    2771             : {
    2772             :         GF_M2TS_Mux_Program *prog;
    2773             : 
    2774        6303 :         gf_m2ts_mux_table_update_bitrate(mux, mux->pat);
    2775        6303 :         if (mux->sdt) {
    2776          74 :                 gf_m2ts_mux_table_update_bitrate(mux, mux->sdt);
    2777             :         }
    2778             : 
    2779        6303 :         if (!mux->fixed_rate) {
    2780        5394 :                 mux->bit_rate = 0;
    2781             : 
    2782             :                 /*get PAT bitrate*/
    2783        5394 :                 mux->bit_rate += mux->pat->bit_rate;
    2784        5394 :                 if (mux->sdt) {
    2785          74 :                         mux->bit_rate += mux->sdt->bit_rate;
    2786             :                 }
    2787             :         }
    2788             : 
    2789        6303 :         prog = mux->programs;
    2790       18909 :         while (prog) {
    2791        6303 :                 GF_M2TS_Mux_Stream *stream = prog->streams;
    2792       23230 :                 while (stream) {
    2793       10624 :                         if (!mux->fixed_rate) {
    2794        8806 :                                 mux->bit_rate += stream->bit_rate;
    2795             :                         }
    2796             :                         /*reset mux time*/
    2797       10624 :                         if (reset_time) stream->time.sec = stream->time.nanosec = 0;
    2798       10624 :                         stream = stream->next;
    2799             :                 }
    2800             :                 /*get PMT bitrate*/
    2801        6303 :                 gf_m2ts_mux_table_update_bitrate(mux, prog->pmt);
    2802             : 
    2803        6303 :                 if (!mux->fixed_rate) {
    2804        5394 :                         mux->bit_rate += prog->pmt->bit_rate;
    2805             :                 }
    2806             : 
    2807        6303 :                 prog = prog->next;
    2808             :         }
    2809             : 
    2810             :         /*reset mux time*/
    2811        6303 :         if (reset_time) {
    2812          37 :                 mux->time.sec = mux->time.nanosec = 0;
    2813          37 :                 mux->init_sys_time = 0;
    2814             :         }
    2815             : 
    2816        6303 :         if (!mux->bit_rate) {
    2817           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] No bitrates set in VBR mux mode, using 100kbps\n"));
    2818           0 :                 mux->bit_rate=100000;
    2819             :         }
    2820        6303 : }
    2821             : 
    2822             : GF_EXPORT
    2823          37 : u32 gf_m2ts_get_sys_clock(GF_M2TS_Mux *muxer)
    2824             : {
    2825          37 :         return (u32) (gf_sys_clock_high_res() - muxer->init_sys_time)/1000;
    2826             : }
    2827             : 
    2828             : GF_EXPORT
    2829          37 : u32 gf_m2ts_get_ts_clock(GF_M2TS_Mux *muxer)
    2830             : {
    2831             :         u32 now, init;
    2832          37 :         init = muxer->init_ts_time.sec*1000 + muxer->init_ts_time.nanosec/1000000;
    2833          37 :         now = muxer->time.sec*1000 + muxer->time.nanosec/1000000;
    2834          37 :         return now-init;
    2835             : }
    2836             : 
    2837             : GF_EXPORT
    2838       32993 : u64 gf_m2ts_get_ts_clock_90k(GF_M2TS_Mux *muxer)
    2839             : {
    2840             :         u64 now, init;
    2841       32993 :         init = ((u64)muxer->init_ts_time.sec) * 90000;
    2842       32993 :         init += ((u64) muxer->init_ts_time.nanosec/1000) * 9 / 100;
    2843       32993 :         now = ((u64) muxer->time.sec)*90000;
    2844       32993 :         now += ((u64) muxer->time.nanosec/1000) * 9 / 100;
    2845       32993 :         return now - init;
    2846             : }
    2847             : 
    2848             : GF_EXPORT
    2849          37 : GF_Err gf_m2ts_mux_use_single_au_pes_mode(GF_M2TS_Mux *muxer, GF_M2TS_PackMode au_pes_mode)
    2850             : {
    2851          37 :         if (!muxer) return GF_BAD_PARAM;
    2852          37 :         muxer->au_pes_mode = au_pes_mode;
    2853          37 :         return GF_OK;
    2854             : }
    2855             : 
    2856             : GF_EXPORT
    2857          48 : GF_Err gf_m2ts_mux_set_initial_pcr(GF_M2TS_Mux *muxer, u64 init_pcr_value)
    2858             : {
    2859          48 :         if (!muxer) return GF_BAD_PARAM;
    2860          48 :         muxer->init_pcr_value = 1 + init_pcr_value;
    2861          48 :         return GF_OK;
    2862             : }
    2863             : 
    2864             : GF_EXPORT
    2865          37 : GF_Err gf_m2ts_mux_enable_pcr_only_packets(GF_M2TS_Mux *muxer, Bool enable_forced_pcr)
    2866             : {
    2867          37 :         if (!muxer) return GF_BAD_PARAM;
    2868          37 :         muxer->enable_forced_pcr = enable_forced_pcr;
    2869          37 :         return GF_OK;
    2870             : }
    2871             : 
    2872             : 
    2873             : GF_EXPORT
    2874      131630 : const u8 *gf_m2ts_mux_process(GF_M2TS_Mux *muxer, GF_M2TSMuxState *status, u32 *usec_till_next)
    2875             : {
    2876             :         GF_M2TS_Mux_Program *program;
    2877             :         GF_M2TS_Mux_Stream *stream, *stream_to_process;
    2878             :         GF_M2TS_Time time, max_time;
    2879             :         u32 nb_streams, nb_streams_done;
    2880             :         u64 now_us;
    2881             :         char *ret;
    2882             :         u32 res, highest_priority;
    2883             :         Bool flush_all_pes = GF_FALSE;
    2884             :         Bool check_max_time = GF_FALSE;
    2885             : 
    2886             :         nb_streams = nb_streams_done = 0;
    2887      131630 :         *status = GF_M2TS_STATE_IDLE;
    2888             : 
    2889      131630 :         muxer->sap_inserted = GF_FALSE;
    2890      131630 :         muxer->last_pid = 0;
    2891             : 
    2892      131630 :         now_us = gf_sys_clock_high_res();
    2893      131630 :         if (muxer->real_time) {
    2894           0 :                 if (!muxer->init_sys_time) {
    2895             :                         //init TS time
    2896           0 :                         muxer->time.sec = muxer->time.nanosec = 0;
    2897           0 :                         gf_m2ts_time_inc(&muxer->time, (u32) (muxer->init_pcr_value ? muxer->init_pcr_value-1 : 0), 27000000);
    2898           0 :                         muxer->init_sys_time = now_us;
    2899           0 :                         muxer->init_ts_time = muxer->time;
    2900             :                 } else {
    2901           0 :                         u64 us_diff = now_us - muxer->init_sys_time;
    2902           0 :                         GF_M2TS_Time now = muxer->init_ts_time;
    2903             :                         gf_m2ts_time_inc(&now, us_diff, 1000000);
    2904           0 :                         if (gf_m2ts_time_less(&now, &muxer->time)) {
    2905           0 :                                 if (usec_till_next) {
    2906           0 :                                         u32 diff = muxer->time.sec - now.sec;
    2907           0 :                                         diff *= 1000000;
    2908           0 :                                         if (now.nanosec <= muxer->time.nanosec) {
    2909           0 :                                                 diff += (muxer->time.nanosec - now.nanosec) / 1000;
    2910             :                                         } else {
    2911             :                                                 assert(diff);
    2912           0 :                                                 diff -= 1000000;
    2913           0 :                                                 diff += (1000000000 + muxer->time.nanosec - now.nanosec) / 1000;
    2914             :                                         }
    2915           0 :                                         *usec_till_next = diff;
    2916             :                                 }
    2917             :                                 return NULL;
    2918             :                         }
    2919             :                 }
    2920             :         }
    2921             : 
    2922             :         stream_to_process = NULL;
    2923      131630 :         time = muxer->time;
    2924             :         max_time.sec = max_time.nanosec = 0;
    2925             : 
    2926             :         /*bitrate have changed*/
    2927      131630 :         if (muxer->needs_reconfig) {
    2928         128 :                 gf_m2ts_mux_update_config(muxer, GF_FALSE);
    2929         128 :                 muxer->needs_reconfig = GF_FALSE;
    2930             :         }
    2931             : 
    2932      131630 :         if (muxer->flush_pes_at_rap && muxer->force_pat) {
    2933         124 :                 program = muxer->programs;
    2934         372 :                 while (program) {
    2935         124 :                         stream = program->streams;
    2936         393 :                         while (stream) {
    2937         145 :                                 if (stream->pes_data_remain) {
    2938             :                                         flush_all_pes = GF_TRUE;
    2939             :                                         break;
    2940             :                                 }
    2941         145 :                                 stream = stream->next;
    2942             :                         }
    2943         124 :                         program = program->next;
    2944             :                 }
    2945             :         }
    2946             : 
    2947         124 :         if (!flush_all_pes) {
    2948             : 
    2949             :                 /*compare PAT and PMT with current mux time
    2950             :                 if non-fixed rate, current mux time is the time of the last packet sent, time test is still valid - it will however not work
    2951             :                 if min access unit duration from all streams is greater than the PSI refresh rate*/
    2952             : 
    2953             :                 /*PAT*/
    2954      131630 :                 res = muxer->pat->process(muxer, muxer->pat);
    2955      217657 :                 if ((res && gf_m2ts_time_less_or_equal(&muxer->pat->time, &time)) || muxer->force_pat) {
    2956        2333 :                         time = muxer->pat->time;
    2957             :                         stream_to_process = muxer->pat;
    2958        2333 :                         if (muxer->force_pat) {
    2959         125 :                                 muxer->force_pat = GF_FALSE;
    2960         125 :                                 muxer->force_pat_pmt_state = GF_SEG_BOUNDARY_FORCE_PMT;
    2961             :                         }
    2962             :                         /*force sending the PAT regardless of other streams*/
    2963             :                         goto send_pck;
    2964             :                 }
    2965             : 
    2966             :                 /*SDT*/
    2967      129297 :                 if (muxer->sdt && !muxer->force_pat_pmt_state) {
    2968        1164 :                         res = muxer->sdt->process(muxer, muxer->sdt);
    2969        1703 :                         if (res && gf_m2ts_time_less_or_equal(&muxer->sdt->time, &time) ) {
    2970          15 :                                 time = muxer->sdt->time;
    2971             :                                 stream_to_process = muxer->sdt;
    2972          15 :                                 goto send_pck;
    2973             :                         }
    2974             :                 }
    2975             : 
    2976             :                 /*PMT, for each program*/
    2977      129282 :                 program = muxer->programs;
    2978      385513 :                 while (program) {
    2979      129282 :                         res = program->pmt->process(muxer, program->pmt);
    2980      213533 :                         if ((res && gf_m2ts_time_less_or_equal(&program->pmt->time, &time)) || (muxer->force_pat_pmt_state==GF_SEG_BOUNDARY_FORCE_PMT)) {
    2981        2333 :                                 time = program->pmt->time;
    2982             :                                 stream_to_process = program->pmt;
    2983        2333 :                                 if (muxer->force_pat_pmt_state==GF_SEG_BOUNDARY_FORCE_PMT)
    2984         125 :                                         muxer->force_pat_pmt_state = GF_SEG_BOUNDARY_FORCE_PCR;
    2985             :                                 /*force sending the PMT regardless of other streams*/
    2986             :                                 goto send_pck;
    2987             :                         }
    2988      126949 :                         program = program->next;
    2989             :                 }
    2990             :         }
    2991             : 
    2992             :         /*if non-fixed rate, just pick the earliest data on all streams*/
    2993      126949 :         if (!muxer->fixed_rate) {
    2994      122313 :                 if (!muxer->real_time) {
    2995             :                         time.sec = 0xFFFFFFFF;
    2996             :                 } else {
    2997             :                         check_max_time = GF_TRUE;
    2998             :                 }
    2999             :         }
    3000             : 
    3001             : #define FORCE_PCR_FIRST 0
    3002             : 
    3003             : #if FORCE_PCR_FIRST
    3004             : 
    3005             :         /*PCR stream, for each program (send them first to avoid PCR to never be sent)*/
    3006             :         program = muxer->programs;
    3007             :         while (program) {
    3008             :                 stream = program->pcr;
    3009             :                 if (!flush_all_pes  || (stream->copy_from_next_packets + stream->pes_data_remain) ) {
    3010             :                         res = stream->process(muxer, stream);
    3011             :                         if (res && gf_m2ts_time_less_or_equal(&stream->time, &time)) {
    3012             :                                 time = stream->time;
    3013             :                                 stream_to_process = stream;
    3014             :                                 goto send_pck;
    3015             :                         }
    3016             :                 }
    3017             :                 program = program->next;
    3018             :         }
    3019             : #endif
    3020             : 
    3021             :         /*all streams for each program*/
    3022             :         highest_priority = 0;
    3023      126949 :         program = muxer->programs;
    3024      380847 :         while (program) {
    3025      126949 :                 stream = program->streams;
    3026      447676 :                 while (stream) {
    3027             : #if FORCE_PCR_FIRST
    3028             :                         if (stream != program->pcr)
    3029             : #endif
    3030             :                         {
    3031      193778 :                                 if (flush_all_pes && !stream->pes_data_remain) {
    3032           0 :                                         nb_streams++;
    3033           0 :                                         stream = stream->next;
    3034           0 :                                         continue;
    3035             :                                 }
    3036             : 
    3037      193778 :                                 res = stream->process(muxer, stream);
    3038             :                                 /*next is rap on this stream, check flushing of other pes (we could use a goto)*/
    3039      193778 :                                 if (!flush_all_pes && muxer->force_pat)
    3040             :                                         return gf_m2ts_mux_process(muxer, status, usec_till_next);
    3041             : 
    3042      193778 :                                 if (res) {
    3043             :                                         /*always schedule the earliest data*/
    3044       27001 :                                         if (gf_m2ts_time_less(&stream->time, &time)) {
    3045             :                                                 highest_priority = res;
    3046      121898 :                                                 time = stream->time;
    3047             :                                                 stream_to_process = stream;
    3048             : #if FORCE_PCR_FIRST
    3049             :                                                 goto send_pck;
    3050             : #endif
    3051             :                                         }
    3052       27437 :                                         else if (gf_m2ts_time_equal(&stream->time, &time)) {
    3053             :                                                 /*if the same priority schedule base stream first*/
    3054          76 :                                                 if ((res > highest_priority) || ((res == highest_priority) && !stream->ifce->depends_on_stream)) {
    3055             :                                                         highest_priority = res;
    3056          76 :                                                         time = stream->time;
    3057             :                                                         stream_to_process = stream;
    3058             : #if FORCE_PCR_FIRST
    3059             :                                                         goto send_pck;
    3060             : #endif
    3061             :                                                 }
    3062       27361 :                                         } else if (check_max_time && gf_m2ts_time_less(&max_time, &stream->time)) {
    3063           0 :                                                 max_time = stream->time;
    3064             :                                         }
    3065             :                                 }
    3066             :                         }
    3067      193778 :                         nb_streams++;
    3068      193778 :                         if ((stream->ifce->caps & GF_ESI_STREAM_IS_OVER) && (!res || stream->refresh_rate_ms) )
    3069        5032 :                                 nb_streams_done ++;
    3070             : 
    3071      193778 :                         stream = stream->next;
    3072             :                 }
    3073      126949 :                 program = program->next;
    3074             :         }
    3075             : 
    3076      126949 : send_pck:
    3077             : 
    3078             :         ret = NULL;
    3079      131630 :         if (!stream_to_process) {
    3080        8378 :                 if (nb_streams && (nb_streams==nb_streams_done)) {
    3081        1212 :                         *status = GF_M2TS_STATE_EOS;
    3082             :                 } else {
    3083        7166 :                         *status = GF_M2TS_STATE_PADDING;
    3084             :                 }
    3085             :                 /* padding packets ?? */
    3086        8378 :                 if (muxer->fixed_rate) {
    3087        3591 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Inserting empty packet at %d:%09d\n", time.sec, time.nanosec));
    3088        3591 :                         ret = muxer->null_pck;
    3089        3591 :                         muxer->tot_pad_sent++;
    3090             :                 }
    3091             :         } else {
    3092      123252 :                 if (stream_to_process->tables) {
    3093        4684 :                         gf_m2ts_mux_table_get_next_packet(muxer, stream_to_process, muxer->dst_pck);
    3094             :                 } else {
    3095      118568 :                         gf_m2ts_mux_pes_get_next_packet(stream_to_process, muxer->dst_pck);
    3096      118568 :                         if (stream_to_process->pck_sap_type) {
    3097        9113 :                                 muxer->sap_inserted = GF_TRUE;
    3098        9113 :                                 muxer->sap_type = stream_to_process->pck_sap_type;
    3099        9113 :                                 muxer->sap_time = stream_to_process->pck_sap_time;
    3100             :                         }
    3101      118568 :                         muxer->last_pts = stream_to_process->curr_pck.cts;
    3102      118568 :                         muxer->last_pid = stream_to_process->pid;
    3103             :                 }
    3104             : 
    3105      123252 :                 ret = muxer->dst_pck;
    3106      123252 :                 *status = GF_M2TS_STATE_DATA;
    3107             : 
    3108      123252 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sending %s from PID %d at %d:%09d - mux time %d:%09d\n", stream_to_process->tables ? "table" : "PES", stream_to_process->pid, time.sec, time.nanosec, muxer->time.sec, muxer->time.nanosec));
    3109             : 
    3110      123252 :                 if (nb_streams && (nb_streams==nb_streams_done))
    3111           0 :                         *status = GF_M2TS_STATE_EOS;
    3112             :         }
    3113             :         if (ret) {
    3114      126843 :                 muxer->tot_pck_sent++;
    3115             :                 /*increment time*/
    3116      126843 :                 if (muxer->fixed_rate ) {
    3117        4708 :                         gf_m2ts_time_inc(&muxer->time, 1504/*188*8*/, muxer->bit_rate);
    3118             :                 }
    3119      122135 :                 else if (muxer->real_time) {
    3120           0 :                         u64 us_diff = gf_sys_clock_high_res() - muxer->init_sys_time;
    3121           0 :                         muxer->time = muxer->init_ts_time;
    3122             :                         gf_m2ts_time_inc(&muxer->time, us_diff, 1000000);
    3123             :                 }
    3124             :                 /*if a stream was found, use it*/
    3125      122135 :                 else if (stream_to_process) {
    3126       85069 :                         if (gf_m2ts_time_less_or_equal(&muxer->time, &time))
    3127       58172 :                                 muxer->time = time;
    3128             :                 }
    3129             : 
    3130      126843 :                 muxer->pck_sent_over_br_window++;
    3131      126843 :                 if (now_us - muxer->last_br_time_us > 1000000) {
    3132          21 :                         u64 size = 8*188*muxer->pck_sent_over_br_window;
    3133          21 :                         muxer->average_birate_kbps = (u32) (size*1000 / (now_us - muxer->last_br_time_us));
    3134          21 :                         muxer->last_br_time_us = now_us;
    3135          21 :                         muxer->pck_sent_over_br_window=0;
    3136             :                 }
    3137        4787 :         } else if (muxer->real_time && !muxer->fixed_rate) {
    3138             : //              u64 us_diff = gf_sys_clock_high_res() - muxer->init_sys_time;
    3139             : //              muxer->time = muxer->init_ts_time;
    3140             : //              gf_m2ts_time_inc(&muxer->time, us_diff, 1000000);
    3141           0 :                 muxer->time = max_time;
    3142             :         }
    3143             :         return ret;
    3144             : }
    3145             : 
    3146             : #endif /*GPAC_DISABLE_MPEG2TS_MUX*/

Generated by: LCOV version 1.13