From 8b5bc7296b580d4989f491aa5f4d1cd0fa51afc5 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Fri, 14 Jun 2013 19:06:22 +0100 Subject: [PATCH 01/27] First stab at TS mux reconfiguration --- common.h | 2 ++ libmpegts.c | 55 +++++++++++++++++++++++++++++++++++------------------ libmpegts.h | 9 +++++++++ 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/common.h b/common.h index fc371e6..8cd968e 100644 --- a/common.h +++ b/common.h @@ -48,6 +48,7 @@ #define TS_PACKET_SIZE 188 #define TS_CLOCK 27000000LL #define TS_START 10 +#define TIMESTAMP_CLOCK 90000LL // arbitrary #define MAX_PROGRAMS 100 @@ -284,6 +285,7 @@ struct ts_writer_t uint64_t bytes_written; uint64_t packets_written; + uint64_t pcr_start; int ts_type; int ts_id; diff --git a/libmpegts.c b/libmpegts.c index bf6a649..f83d901 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -204,12 +204,12 @@ static int check_pcr( ts_writer_t *w, ts_int_program_t *program ) static int64_t get_pcr_int( ts_writer_t *w, double offset ) { - return (int64_t)((8.0 * (w->packets_written * TS_PACKET_SIZE + offset) / w->ts_muxrate) * TS_CLOCK + 0.5) + TS_START * TS_CLOCK; + return (int64_t)((8.0 * (w->packets_written * TS_PACKET_SIZE + offset) / w->ts_muxrate) * TS_CLOCK + 0.5) + w->pcr_start; } static double get_pcr_double( ts_writer_t *w, double offset ) { - return (8.0 * (w->packets_written * TS_PACKET_SIZE + offset) / w->ts_muxrate) + TS_START; + return (8.0 * (w->packets_written * TS_PACKET_SIZE + offset) / w->ts_muxrate) + (double)w->pcr_start / TS_CLOCK; } /**** Buffer management ****/ @@ -853,6 +853,20 @@ static int check_bitstream( ts_writer_t *w ) return 0; } +/* set updatable ts parameters */ +static void update_ts_params( ts_writer_t *w, ts_main_t *params ) +{ + w->ts_muxrate = params->muxrate; + w->cbr = params->cbr; + w->legacy_constraints = params->legacy_constraints; + + w->pcr_period = params->pcr_period ? params->pcr_period : PCR_MAX_RETRANS_TIME; + w->pat_period = params->pat_period ? params->pat_period : PAT_MAX_RETRANS_TIME; + w->sdt_period = params->sdt_period ? params->sdt_period : SDT_MAX_RETRANS_TIME; + + w->r_sys = MAX( R_SYS_DEFAULT, (double)w->ts_muxrate / 500 ); +} + ts_writer_t *ts_create_writer( void ) { ts_writer_t *w = calloc( 1, sizeof(*w) ); @@ -1048,22 +1062,16 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) cur_program->pcr_stream = pcr_stream; } - w->ts_id = params->ts_id; - w->ts_muxrate = params->muxrate; - w->cbr = params->cbr; - w->ts_type = params->ts_type; + update_ts_params( w, params ); + w->network_pid = params->network_pid; - w->legacy_constraints = params->legacy_constraints; - - w->pcr_period = params->pcr_period ? params->pcr_period : PCR_MAX_RETRANS_TIME; - w->pat_period = params->pat_period ? params->pat_period : PAT_MAX_RETRANS_TIME; - w->sdt_period = params->sdt_period ? params->sdt_period : SDT_MAX_RETRANS_TIME; - + w->ts_type = params->ts_type; w->network_id = params->network_id ? params->network_id : DEFAULT_NID; - + w->ts_id = params->ts_id; w->tb.buf_size = TB_SIZE; w->rx_sys = RX_SYS; - w->r_sys = MAX( R_SYS_DEFAULT, (double)w->ts_muxrate / 500 ); + + w->pcr_start = TS_START * TS_CLOCK; // FIXME realloc if necessary @@ -1081,6 +1089,17 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) return 0; } +int ts_update_transport_stream( ts_writer_t *w, ts_main_t *params ) +{ + int64_t cur_pcr = get_pcr_int( w, 0 ); + if( params->muxrate != w->ts_muxrate ) + { + update_ts_params( w, params ); + w->packets_written = 0; + w->pcr_start = cur_pcr; + } +} + /* Codec-specific features */ int ts_setup_mpegvideo_stream( ts_writer_t *w, int pid, int level, int profile, int vbv_maxrate, int vbv_bufsize, int frame_rate ) @@ -1601,14 +1620,14 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t new_pes[i]->stream = stream; new_pes[i]->random_access = !!frames[i].random_access; new_pes[i]->priority = !!frames[i].priority; - new_pes[i]->dts = frames[i].dts + TS_START * 90000LL; - new_pes[i]->pts = frames[i].pts + TS_START * 90000LL; + new_pes[i]->dts = frames[i].dts + TS_START * TIMESTAMP_CLOCK; + new_pes[i]->pts = frames[i].pts + TS_START * TIMESTAMP_CLOCK; if( IS_VIDEO( stream ) ) { new_pes[i]->frame_type = frames[i].frame_type; - new_pes[i]->initial_arrival_time = frames[i].cpb_initial_arrival_time + TS_START * 27000000LL; - new_pes[i]->final_arrival_time = frames[i].cpb_final_arrival_time + TS_START * 27000000LL; + new_pes[i]->initial_arrival_time = frames[i].cpb_initial_arrival_time + TS_START * TS_CLOCK; + new_pes[i]->final_arrival_time = frames[i].cpb_final_arrival_time + TS_START * TS_CLOCK; new_pes[i]->ref_pic_idc = frames[i].ref_pic_idc; new_pes[i]->write_pulldown_info = frames[i].write_pulldown_info; new_pes[i]->pic_struct = frames[i].pic_struct; diff --git a/libmpegts.h b/libmpegts.h index ff7415f..ffc996f 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -329,6 +329,15 @@ typedef struct ts_main_t int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ); +/* update transport stream + * + * muxrate is the only tested parameter + * + * TODO: implement versioning so other parameters can be updated + * + */ +int ts_update_transport_stream( ts_writer_t *w, ts_main_t *params ); + /**** Additional Codec-Specific functions ****/ /* Many formats require extra information. Setup the relevant information using the following functions */ From 75b0b98d0d9d9d4b6240f7816bf15cff3781a2e4 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Fri, 14 Jun 2013 19:14:26 +0100 Subject: [PATCH 02/27] Make ts_update_transport_stream void for the time being --- libmpegts.c | 2 +- libmpegts.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index f83d901..94516ea 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1089,7 +1089,7 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) return 0; } -int ts_update_transport_stream( ts_writer_t *w, ts_main_t *params ) +void ts_update_transport_stream( ts_writer_t *w, ts_main_t *params ) { int64_t cur_pcr = get_pcr_int( w, 0 ); if( params->muxrate != w->ts_muxrate ) diff --git a/libmpegts.h b/libmpegts.h index ffc996f..2d694e9 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -336,7 +336,7 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ); * TODO: implement versioning so other parameters can be updated * */ -int ts_update_transport_stream( ts_writer_t *w, ts_main_t *params ); +void ts_update_transport_stream( ts_writer_t *w, ts_main_t *params ); /**** Additional Codec-Specific functions ****/ /* Many formats require extra information. Setup the relevant information using the following functions */ From 5c123b89f907174bf091bebdfc34595d20d1c085 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Fri, 14 Jun 2013 20:34:41 +0100 Subject: [PATCH 03/27] Improve PCR generation after reconfig --- libmpegts.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index 94516ea..1ad0e20 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -190,14 +190,10 @@ static void write_iso_lang_descriptor( bs_t *s, ts_int_stream_t *stream ) static int check_pcr( ts_writer_t *w, ts_int_program_t *program ) { // if the next packet written goes over the max pcr retransmit boundary, write the pcr in the next packet - double next_pkt_pcr = ((w->packets_written * TS_PACKET_SIZE) + (TS_PACKET_SIZE + 7)) * 8.0 / w->ts_muxrate - - (double)program->last_pcr / TS_CLOCK; - next_pkt_pcr += TS_START; + int64_t next_pkt_pcr = get_pcr_int( w, (TS_PACKET_SIZE + 7) * 8 ) - program->last_pcr; - if( next_pkt_pcr >= (double)w->pcr_period / 1000 ) - { + if( next_pkt_pcr >= w->pcr_period * (TS_CLOCK/1000) ) return 1; - } return 0; } @@ -2025,7 +2021,7 @@ int increase_pcr( ts_writer_t *w, int num_packets, int imaginary ) // TODO do this for all programs ts_int_program_t *program = w->programs[0]; - double next_pcr = TS_START + (w->packets_written + num_packets) * 8.0 * TS_PACKET_SIZE / w->ts_muxrate; + double next_pcr = get_pcr_double( w, num_packets * TS_PACKET_SIZE ); /* buffer drip (TODO: all buffers?) */ drip_buffer( w, program, w->rx_sys, &w->tb, next_pcr ); for( int i = 0; i < program->num_streams; i++ ) @@ -2037,6 +2033,7 @@ int increase_pcr( ts_writer_t *w, int num_packets, int imaginary ) if( !imaginary ) { + // FIXME this is wrong for multiple packets if( w->num_pcrs > w->pcr_list_alloced ) { temp = realloc( w->pcr_list, w->pcr_list_alloced * 2 * sizeof(int64_t) ); From ea148ff4af8074519b596070ee66f04d7c258a49 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Fri, 14 Jun 2013 20:37:14 +0100 Subject: [PATCH 04/27] Fix build --- libmpegts.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index 1ad0e20..73c604d 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -187,6 +187,16 @@ static void write_iso_lang_descriptor( bs_t *s, ts_int_stream_t *stream ) } /**** PCR functions ****/ +static int64_t get_pcr_int( ts_writer_t *w, double offset ) +{ + return (int64_t)((8.0 * (w->packets_written * TS_PACKET_SIZE + offset) / w->ts_muxrate) * TS_CLOCK + 0.5) + w->pcr_start; +} + +static double get_pcr_double( ts_writer_t *w, double offset ) +{ + return (8.0 * (w->packets_written * TS_PACKET_SIZE + offset) / w->ts_muxrate) + (double)w->pcr_start / TS_CLOCK; +} + static int check_pcr( ts_writer_t *w, ts_int_program_t *program ) { // if the next packet written goes over the max pcr retransmit boundary, write the pcr in the next packet @@ -198,16 +208,6 @@ static int check_pcr( ts_writer_t *w, ts_int_program_t *program ) return 0; } -static int64_t get_pcr_int( ts_writer_t *w, double offset ) -{ - return (int64_t)((8.0 * (w->packets_written * TS_PACKET_SIZE + offset) / w->ts_muxrate) * TS_CLOCK + 0.5) + w->pcr_start; -} - -static double get_pcr_double( ts_writer_t *w, double offset ) -{ - return (8.0 * (w->packets_written * TS_PACKET_SIZE + offset) / w->ts_muxrate) + (double)w->pcr_start / TS_CLOCK; -} - /**** Buffer management ****/ static void add_to_buffer( buffer_t *buffer ) { From 28333981bb89fd1b9f4a97090d8a53ab4f2b687b Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Tue, 28 Jan 2014 18:24:23 +0000 Subject: [PATCH 05/27] Attempt to improve PSI transmission --- libmpegts.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index e4cfea8..53e2f29 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -641,11 +641,11 @@ static int write_pmt( ts_writer_t *w, ts_int_program_t *program ) return 0; } -static void retransmit_psi_and_si( ts_writer_t *w, ts_int_program_t *program, int first ) +static void retransmit_psi_and_si( ts_writer_t *w, ts_int_program_t *program ) { // TODO make this work with multiple programs int64_t cur_pcr = get_pcr_int( w, 0 ); - if( cur_pcr - w->last_pat >= w->pat_period * 27000LL || first ) + if( cur_pcr - w->last_pat >= w->pat_period * 27000LL || !w->last_pat ) { /* Although it is not in line with the mux strategy it is good practice to write PAT and PMT together */ w->last_pat = cur_pcr; @@ -655,7 +655,7 @@ static void retransmit_psi_and_si( ts_writer_t *w, ts_int_program_t *program, in cur_pcr = get_pcr_int( w, 0 ); - if( w->sdt && ( cur_pcr - w->last_sdt >= w->sdt_period * 27000LL || first ) ) + if( w->sdt && ( cur_pcr - w->last_sdt >= w->sdt_period * 27000LL || !w->last_sdt ) ) { w->last_sdt = cur_pcr; write_sdt( w ); @@ -1667,7 +1667,6 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t { if( write_pcr_empty( w, program, 1 ) < 0 ) return -1; - retransmit_psi_and_si( w, program, 1 ); w->first_input = 1; } @@ -1717,6 +1716,8 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t /* Check all the non-video packets first */ if( !need_pcr ) { + retransmit_psi_and_si( w, program ); + for( int i = 0; i < w->num_buffered_frames; i++ ) { stream = queued_pes[i]->stream; @@ -1872,8 +1873,6 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t free( pes->data ); free( pes ); } - - retransmit_psi_and_si( w, program, 0 ); } else /* no packets can be written */ { From e8d8d6d0087234f54b30a565b44d14d3dab816ce Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 10 May 2014 18:13:55 +0200 Subject: [PATCH 06/27] Add Opus support --- common.h | 3 +++ dvb/dvb.h | 1 + libmpegts.c | 32 +++++++++++++++++++++++++++++++- libmpegts.h | 11 ++++++++++- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/common.h b/common.h index fc371e6..79d91c3 100644 --- a/common.h +++ b/common.h @@ -201,6 +201,9 @@ typedef struct int aac_profile; int aac_channel_map; + /* Opus */ + int opus_channel_map; + /* ATSC */ /* DVB */ diff --git a/dvb/dvb.h b/dvb/dvb.h index 9cc7c30..e881a64 100644 --- a/dvb/dvb.h +++ b/dvb/dvb.h @@ -32,6 +32,7 @@ #define DVB_ADAPTATION_FIELD_DATA_DESCRIPTOR 0x70 #define DVB_EAC3_DESCRIPTOR_TAG 0x7a #define DVB_AAC_DESCRIPTOR_TAG 0x7c +#define DVB_EXTENSION_DESCRIPTOR_TAG 0x7f /* PIDs */ #define SDT_PID 0x0011 diff --git a/libmpegts.c b/libmpegts.c index 53e2f29..fdb7499 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -29,7 +29,7 @@ #include "crc/crc.h" #include -static const int steam_type_table[27][2] = +static const int steam_type_table[28][2] = { { LIBMPEGTS_VIDEO_MPEG2, VIDEO_MPEG2 }, { LIBMPEGTS_VIDEO_AVC, VIDEO_AVC }, @@ -57,6 +57,7 @@ static const int steam_type_table[27][2] = { LIBMPEGTS_DVB_VBI, PRIVATE_DATA }, { LIBMPEGTS_ANCILLARY_RDD11, PRIVATE_DATA }, { LIBMPEGTS_ANCILLARY_2038, PRIVATE_DATA }, + { LIBMPEGTS_AUDIO_OPUS, PRIVATE_DATA }, { 0 }, }; @@ -186,6 +187,15 @@ static void write_iso_lang_descriptor( bs_t *s, ts_int_stream_t *stream ) bs_write(s, 8, stream->audio_type ); // audio_type } +/** Misc descriptors **/ +static void write_opus_descriptor( bs_t *s, ts_int_stream_t *stream ) +{ + bs_write( s, 8, DVB_EXTENSION_DESCRIPTOR_TAG ); // descriptor_tag + bs_write( s, 8, 0x2 ); // descriptor_length + bs_write( s, 8, 0x80 ); // descriptor_tag_extension (User defined) + bs_write( s, 8, stream->opus_channel_map ); // channel_config_code +} + /**** PCR functions ****/ static int check_pcr( ts_writer_t *w, ts_int_program_t *program ) { @@ -568,6 +578,11 @@ static int write_pmt( ts_writer_t *w, ts_int_program_t *program ) write_registration_descriptor( &q, PRIVATE_DATA_DESCRIPTOR_TAG, 4, "VANC" ); write_anc_data_descriptor( &q ); } + else if( stream->stream_format == LIBMPEGTS_AUDIO_OPUS ) + { + write_registration_descriptor( &q, PRIVATE_DATA_DESCRIPTOR_TAG, 4, "Opus" ); + write_opus_descriptor( &q, stream ); + } // TODO other stream_type descriptors @@ -1331,6 +1346,21 @@ int ts_setup_302m_stream( ts_writer_t *w, int pid, int bit_depth, int num_channe return 0; } +int ts_setup_opus_stream( ts_writer_t *w, int pid, int channel_map ) +{ + ts_int_stream_t *stream = find_stream( w, pid ); + + if( !stream ) + { + fprintf( stderr, "Invalid PID\n" ); + return -1; + } + + stream->opus_channel_map = channel_map; + + return 0; +} + int ts_setup_dvb_subtitles( ts_writer_t *w, int pid, int has_dds, int num_subtitles, ts_dvb_sub_t *subtitles ) { if( w->ts_type == TS_TYPE_BLU_RAY ) diff --git a/libmpegts.h b/libmpegts.h index ff7415f..33366f1 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -69,7 +69,7 @@ #define LIBMPEGTS_DVB_VBI 130 /* Misc */ - +#define LIBMPEGTS_AUDIO_OPUS 160 /**** Stream IDs ****/ /* SMPTE 302M, AC3, DVB subtitles and Teletext use Private Stream 1 */ @@ -412,6 +412,15 @@ int ts_setup_mpeg4_aac_stream( ts_writer_t *w, int pid, int profile_and_level, i int ts_setup_302m_stream( ts_writer_t *w, int pid, int bit_depth, int num_channels ); +/* Opus */ + +#define LIBMPEGTS_CHANNEL_CONFIG_DUAL_MONO 0x00 +#define LIBMPEGTS_CHANNEL_CONFIG_MONO 0x01 +#define LIBMPEGTS_CHANNEL_CONFIG_STEREO 0x02 + +int ts_setup_opus_stream( ts_writer_t *w, int pid, int channel_map ); + + /**** DVB Specific Information ****/ /* DVB Subtitles */ From b69d839351534df17aae7fc5833eb41970f75d20 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Wed, 9 Jul 2014 16:34:41 +0100 Subject: [PATCH 07/27] Correct Opus T-STD buffers --- libmpegts.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libmpegts.c b/libmpegts.c index fdb7499..52739d9 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1037,7 +1037,8 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) cur_stream->tb.buf_size = TB_SIZE; /* setup T-STD buffers when audio buffers sizes are independent of number of channels */ - if( cur_stream->stream_format == LIBMPEGTS_AUDIO_MPEG1 || cur_stream->stream_format == LIBMPEGTS_AUDIO_MPEG2 ) + if( cur_stream->stream_format == LIBMPEGTS_AUDIO_MPEG1 || cur_stream->stream_format == LIBMPEGTS_AUDIO_MPEG2 || + cur_stream->stream_format == LIBMPEGTS_AUDIO_OPUS ) { /* use the defaults */ cur_stream->rx = MISC_AUDIO_RXN; From 720e67fbd26f867e65cc95fbee5f9053228b80f4 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Thu, 24 Jul 2014 00:01:06 +0100 Subject: [PATCH 08/27] Fix registration descriptors --- libmpegts.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index f87e7ab..450b9c1 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -556,7 +556,7 @@ static int write_pmt( ts_writer_t *w, ts_int_program_t *program ) // TODO } else if( stream->stream_format == LIBMPEGTS_AUDIO_302M ) - write_registration_descriptor( &q, PRIVATE_DATA_DESCRIPTOR_TAG, 4, "BSSD" ); + write_registration_descriptor( &q, REGISTRATION_DESCRIPTOR_TAG, 4, "BSSD" ); else if( stream->stream_format == LIBMPEGTS_DVB_SUB ) write_dvb_subtitling_descriptor( &q, stream ); else if( stream->stream_format == LIBMPEGTS_DVB_TELETEXT ) @@ -568,15 +568,15 @@ static int write_pmt( ts_writer_t *w, ts_int_program_t *program ) write_teletext_descriptor( &q, stream, 1 ); } else if( stream->stream_format == LIBMPEGTS_ANCILLARY_RDD11 ) - write_registration_descriptor( &q, PRIVATE_DATA_DESCRIPTOR_TAG, 4, "LU-A" ); + write_registration_descriptor( &q, REGISTRATION_DESCRIPTOR_TAG, 4, "LU-A" ); else if( stream->stream_format == LIBMPEGTS_ANCILLARY_2038 ) { - write_registration_descriptor( &q, PRIVATE_DATA_DESCRIPTOR_TAG, 4, "VANC" ); + write_registration_descriptor( &q, REGISTRATION_DESCRIPTOR_TAG, 4, "VANC" ); write_anc_data_descriptor( &q ); } else if( stream->stream_format == LIBMPEGTS_AUDIO_OPUS ) { - write_registration_descriptor( &q, PRIVATE_DATA_DESCRIPTOR_TAG, 4, "Opus" ); + write_registration_descriptor( &q, REGISTRATION_DESCRIPTOR_TAG, 4, "Opus" ); write_opus_descriptor( &q, stream ); } From 3703d0986bb97db62e00ae907479b67f1fb6fff0 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 29 Nov 2014 22:50:56 +0000 Subject: [PATCH 09/27] Improve T-STD for 302M --- libmpegts.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index 450b9c1..727ad63 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1059,6 +1059,8 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) cur_stream->rx = MISC_AUDIO_RXN; cur_stream->mb.buf_size = w->ts_type == TS_TYPE_ATSC || w->ts_type == TS_TYPE_CABLELABS ? AC3_BS_ATSC : AC3_BS_DVB; } + else if( cur_stream->stream_format == LIBMPEGTS_AUDIO_302M ) + cur_stream->mb.buf_size = (1 << 16) - 512; cur_program->streams[cur_program->num_streams] = cur_stream; cur_program->num_streams++; @@ -1344,20 +1346,8 @@ int ts_setup_302m_stream( ts_writer_t *w, int pid, int bit_depth, int num_channe return -1; } - if( stream->lpcm_ctx ) - free( stream->lpcm_ctx ); - - stream->lpcm_ctx = calloc( 1, sizeof(lpcm_stream_ctx_t) ); - if( !stream->lpcm_ctx ) - return -1; - - stream->lpcm_ctx->bits_per_sample = bit_depth; - stream->lpcm_ctx->num_channels = num_channels; - stream->mb.buf_size = SMPTE_302M_AUDIO_BS; - - /* 302M frame size is bit_depth / 4 + 1 */ - stream->rx = 1.2 * ((bit_depth >> 2) + 1) * SMPTE_302M_AUDIO_SR * 8; + stream->rx = 1.2 * 6 * SMPTE_302M_AUDIO_SR * 8; return 0; } From 31eccd1589f62a10951f8f04d857c565f70463d8 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 29 Nov 2014 23:05:51 +0000 Subject: [PATCH 10/27] Attempt to improve 302M some more --- libmpegts.c | 36 +++--------------------------------- libmpegts.h | 1 + 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index 727ad63..e4ec993 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1060,7 +1060,7 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) cur_stream->mb.buf_size = w->ts_type == TS_TYPE_ATSC || w->ts_type == TS_TYPE_CABLELABS ? AC3_BS_ATSC : AC3_BS_DVB; } else if( cur_stream->stream_format == LIBMPEGTS_AUDIO_302M ) - cur_stream->mb.buf_size = (1 << 16) - 512; + cur_stream->mb.buf_size = SMPTE_302M_AUDIO_BS; cur_program->streams[cur_program->num_streams] = cur_stream; cur_program->num_streams++; @@ -1320,38 +1320,6 @@ int ts_setup_mpeg4_aac_stream( ts_writer_t *w, int pid, int profile_and_level, i return 0; }; -int ts_setup_302m_stream( ts_writer_t *w, int pid, int bit_depth, int num_channels ) -{ - if( w->ts_type == TS_TYPE_BLU_RAY ) - { - fprintf( stderr, "SMPTE 302M not allowed in Blu-Ray\n" ); - return -1; - } - else if( !(bit_depth == 16 || bit_depth == 20 || bit_depth == 24) ) - { - fprintf( stderr, "Invalid Bit Depth for SMPTE 302M\n" ); - return -1; - } - else if( (num_channels & 1) || num_channels <= 0 || num_channels > 8 ) - { - fprintf( stderr, "Invalid number of channels for SMPTE 302M\n" ); - return -1; - } - - ts_int_stream_t *stream = find_stream( w, pid ); - - if( !stream ) - { - fprintf( stderr, "Invalid PID\n" ); - return -1; - } - - stream->mb.buf_size = SMPTE_302M_AUDIO_BS; - stream->rx = 1.2 * 6 * SMPTE_302M_AUDIO_SR * 8; - - return 0; -} - int ts_setup_opus_stream( ts_writer_t *w, int pid, int channel_map ) { ts_int_stream_t *stream = find_stream( w, pid ); @@ -1649,6 +1617,8 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t new_pes[i]->write_pulldown_info = frames[i].write_pulldown_info; new_pes[i]->pic_struct = frames[i].pic_struct; } + else if( stream->stream_format == LIBMPEGTS_AUDIO_302M ) + new_pes[i]->initial_arrival_time = (new_pes[i]->dts * 300) - frames[i].duration; else if( stream->stream_format == LIBMPEGTS_DVB_TELETEXT ) new_pes[i]->initial_arrival_time = (new_pes[i]->dts - 3600) * 300; /* Teletext is special because data can only stay in the buffer for 40ms */ else if( stream->stream_format == LIBMPEGTS_DVB_SUB ) diff --git a/libmpegts.h b/libmpegts.h index 79d64a0..a546109 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -666,6 +666,7 @@ typedef struct int64_t cpb_final_arrival_time; int64_t dts; int64_t pts; + int64_t duration /* SMPTE 302M only */ int random_access; int priority; From a82d0833b0590526fafc39609333d7690c3cddcf Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 29 Nov 2014 23:08:46 +0000 Subject: [PATCH 11/27] Fix typo --- libmpegts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmpegts.h b/libmpegts.h index a546109..9440fc7 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -666,7 +666,7 @@ typedef struct int64_t cpb_final_arrival_time; int64_t dts; int64_t pts; - int64_t duration /* SMPTE 302M only */ + int64_t duration; /* SMPTE 302M only */ int random_access; int priority; From ff450772ad3e5c7697b64f557c2bb9b3dc3d013c Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sun, 30 Nov 2014 00:09:55 +0000 Subject: [PATCH 12/27] Make some number up for Rmax because SMPTE is too vague --- libmpegts.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libmpegts.c b/libmpegts.c index e4ec993..d78631e 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1060,7 +1060,12 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) cur_stream->mb.buf_size = w->ts_type == TS_TYPE_ATSC || w->ts_type == TS_TYPE_CABLELABS ? AC3_BS_ATSC : AC3_BS_DVB; } else if( cur_stream->stream_format == LIBMPEGTS_AUDIO_302M ) + { + /* Use some made up value because (surprise surprise) SMPTE hasn't defined it properly + * 7 bytes in 24-bit packing * 4 pairs * 48000 * 1.2 */ + cur_stream->rx = 7 * 4 * 48000 * 6 / 5; cur_stream->mb.buf_size = SMPTE_302M_AUDIO_BS; + } cur_program->streams[cur_program->num_streams] = cur_stream; cur_program->num_streams++; From 715d1b399bd9e7708d8159f10a0cb5626c9a56b1 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sun, 30 Nov 2014 00:12:14 +0000 Subject: [PATCH 13/27] Measure Rxn in bits/s --- libmpegts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmpegts.c b/libmpegts.c index d78631e..4085295 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1063,7 +1063,7 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) { /* Use some made up value because (surprise surprise) SMPTE hasn't defined it properly * 7 bytes in 24-bit packing * 4 pairs * 48000 * 1.2 */ - cur_stream->rx = 7 * 4 * 48000 * 6 / 5; + cur_stream->rx = 7 * 4 * 48000 * 8 * 6 / 5; cur_stream->mb.buf_size = SMPTE_302M_AUDIO_BS; } From 0028f15a1fded4ea2a92722a462274808ad93127 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Wed, 13 Jan 2016 23:00:29 +0000 Subject: [PATCH 14/27] Add support for Dirac --- libmpegts.c | 23 +++++++++++++++++++++-- libmpegts.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index 1fcb995..b1c2f38 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -528,6 +528,8 @@ static int write_pmt( ts_writer_t *w, ts_int_program_t *program ) if( w->ts_type == TS_TYPE_BLU_RAY ) write_hdmv_video_registration_descriptor( &q, stream ); } + else if( stream->stream_format == LIBMPEGTS_VIDEO_DIRAC ) + write_registration_descriptor( &q, REGISTRATION_DESCRIPTOR_TAG, 4, "BBCD" ); else if( stream->stream_format == LIBMPEGTS_AUDIO_MPEG1 || stream->stream_format == LIBMPEGTS_AUDIO_MPEG2 ) { @@ -772,9 +774,11 @@ static int write_pes( ts_writer_t *w, ts_int_program_t *program, ts_frame_t *in_ bs_write1( &q, 0 ); // DSM_trick_mode_flag bs_write1( &q, 0 ); // additional_copy_info_flag bs_write1( &q, 0 ); // PES_CRC_flag - bs_write1( &q, 0 ); // PES_extension_flag + bs_write1( &q, stream->stream_format == LIBMPEGTS_VIDEO_DIRAC ); // PES_extension_flag - if( stream->stream_format == LIBMPEGTS_DVB_TELETEXT || stream->stream_format == LIBMPEGTS_DVB_VBI ) + if( stream->stream_format == LIBMPEGTS_VIDEO_DIRAC ) + bs_write( &q, 8, 0x08 ); // PES_header_data_length + else if( stream->stream_format == LIBMPEGTS_DVB_TELETEXT || stream->stream_format == LIBMPEGTS_DVB_VBI ) bs_write( &q, 8, 0x24 ); // PES_header_data_length else if( same_timestamps ) bs_write( &q, 8, 0x05 ); // PES_header_data_length (PTS only) @@ -791,6 +795,21 @@ static int write_pes( ts_writer_t *w, ts_int_program_t *program, ts_frame_t *in_ write_timestamp( &q, out_pes->dts % mod ); // DTS } + if( stream->stream_format == LIBMPEGTS_VIDEO_DIRAC ) + { + bs_write1( &q, 0 ); // PES_private_data_flag + bs_write1( &q, 0 ); // pack_header_field_flag + bs_write1( &q, 0 ); // program_packet_sequence_counter_flag + bs_write1( &q, 0 ); // P-STD_buffer_flag + bs_write( &q, 3, 0x0a ); // reserved + bs_write1( &q, 1 ); // PES_extension_flag_2 + + bs_write1( &q, 1 ); // marker_bit + bs_write( &q, 7, 1 ); // PES_header_data_length + bs_write1( &q, 0 ); // stream_id_extension_flag + bs_write( &q, 7, 0x60 ); // stream_id_extension + } + /* TTX and VBI require extra stuffing */ if( stream->stream_format == LIBMPEGTS_DVB_TELETEXT || stream->stream_format == LIBMPEGTS_DVB_VBI ) { diff --git a/libmpegts.h b/libmpegts.h index 9440fc7..a91557c 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -38,6 +38,7 @@ /* Generic */ #define LIBMPEGTS_VIDEO_MPEG2 1 #define LIBMPEGTS_VIDEO_AVC 2 +#define LIBMPEGTS_VIDEO_DIRAC 3 #define LIBMPEGTS_AUDIO_MPEG1 32 #define LIBMPEGTS_AUDIO_MPEG2 33 From 3837a1b8104a39a99b99ae1509e909f287c0e9ca Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Thu, 14 Jan 2016 17:26:06 +0000 Subject: [PATCH 15/27] Add extended stream-id for Dirac --- libmpegts.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libmpegts.h b/libmpegts.h index a91557c..5274c23 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -83,6 +83,9 @@ /* MPEG Video (all types): 0xe0-0xef */ #define LIBMPEGTS_STREAM_ID_MPEGVIDEO 0xe0 +/* Extended Stream-id */ +#define LIBMPEGTS_STREAM_ID_EXTENDED 0xfd + /**** Blu-Ray Information ****/ /* Blu-Ray Aspect Ratios */ #define LIBMPEGTS_HDMV_AR_4_3 2 From 70c7f05bf097db875d62ed75267ccf4a70fa92dc Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Thu, 14 Jan 2016 18:08:13 +0000 Subject: [PATCH 16/27] Add Dirac stream type --- libmpegts.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libmpegts.c b/libmpegts.c index b1c2f38..1714093 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -33,6 +33,7 @@ static const int steam_type_table[28][2] = { { LIBMPEGTS_VIDEO_MPEG2, VIDEO_MPEG2 }, { LIBMPEGTS_VIDEO_AVC, VIDEO_AVC }, + { LIBMPEGTS_VIDEO_DIRAC, 0xd1 }, { LIBMPEGTS_AUDIO_MPEG1, AUDIO_MPEG1 }, { LIBMPEGTS_AUDIO_MPEG2, AUDIO_MPEG2 }, { LIBMPEGTS_AUDIO_ADTS, AUDIO_ADTS }, From bc85f1528d70be2d14603ea77d038ff05a6b1523 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Thu, 14 Jan 2016 18:12:15 +0000 Subject: [PATCH 17/27] Fix stream_type_table length --- libmpegts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmpegts.c b/libmpegts.c index 1714093..a261ac4 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -29,7 +29,7 @@ #include "crc/crc.h" #include -static const int steam_type_table[28][2] = +static const int steam_type_table[29][2] = { { LIBMPEGTS_VIDEO_MPEG2, VIDEO_MPEG2 }, { LIBMPEGTS_VIDEO_AVC, VIDEO_AVC }, From d477f9d1f8f306b0a8c97801c89dd8a08d5d9273 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Mon, 18 Jan 2016 13:11:24 +0000 Subject: [PATCH 18/27] Improve dirac some more --- common.h | 2 +- libmpegts.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/common.h b/common.h index c770ff8..1e1be73 100644 --- a/common.h +++ b/common.h @@ -98,7 +98,7 @@ #define MIN(a,b) ( (a)<(b) ? (a) : (b) ) #define MAX(a,b) ( (a)>(b) ? (a) : (b) ) -#define IS_VIDEO(x) ( x->stream_format == LIBMPEGTS_VIDEO_MPEG2 || x->stream_format == LIBMPEGTS_VIDEO_AVC ) +#define IS_VIDEO(x) ( x->stream_format == LIBMPEGTS_VIDEO_MPEG2 || x->stream_format == LIBMPEGTS_VIDEO_AVC || x->stream_format == LIBMPEGTS_VIDEO_DIRAC ) /* Internal Program & Stream Structures */ typedef struct diff --git a/libmpegts.c b/libmpegts.c index a261ac4..06864cb 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1087,6 +1087,19 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) cur_stream->rx = 7 * 4 * 48000 * 8 * 6 / 5; cur_stream->mb.buf_size = SMPTE_302M_AUDIO_BS; } + else if( cur_stream->stream_format == LIBMPEGTS_VIDEO_DIRAC ) + { +#define DIRAC_MAX_BITRATE 10000000 + int bitrate = DIRAC_MAX_BITRATE * 1.2; + int bs_mux = 0.004 * bitrate; + int bs_oh = 1.0 * bitrate / 50.0; + + cur_stream->mb.buf_size = bs_mux + bs_oh; + cur_stream->eb.buf_size = 10000000*8; + + cur_stream->rx = bitrate; + cur_stream->rbx = bitrate; + } cur_program->streams[cur_program->num_streams] = cur_stream; cur_program->num_streams++; From 5dbd0148292a2081db2b11c0e02147bd5a08160f Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Mon, 18 Jan 2016 14:27:16 +0000 Subject: [PATCH 19/27] Set Dirac PES_packet_length to zero --- libmpegts.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libmpegts.c b/libmpegts.c index 06864cb..b0fc5d0 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -823,7 +823,8 @@ static int write_pes( ts_writer_t *w, ts_int_program_t *program, ts_frame_t *in_ bs_flush( &q ); total_size = in_frame->size + (bs_pos( &q ) >> 3); - if( stream->stream_format == LIBMPEGTS_VIDEO_MPEG2 || stream->stream_format == LIBMPEGTS_VIDEO_AVC ) + if( stream->stream_format == LIBMPEGTS_VIDEO_MPEG2 || stream->stream_format == LIBMPEGTS_VIDEO_AVC || + stream->stream_format == LIBMPEGTS_VIDEO_DIRAC ) bs_write( &s, 16, 0 ); // PES_packet_length else bs_write( &s, 16, total_size ); // PES_packet_length From 6eaf49a5fdcc1b445361f8b3a54a5a7afa68c0f2 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Thu, 7 Jul 2016 16:19:43 +0100 Subject: [PATCH 20/27] Remove incorrect NULL check. Fixes some high bitrate streams. --- libmpegts.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index b0fc5d0..b7490aa 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -411,11 +411,6 @@ static int eject_queued_pmt( ts_writer_t *w, ts_int_program_t *program, bs_t *s memmove( &program->pmt_packets[0], &program->pmt_packets[1], (program->num_queued_pmt-1) * sizeof(uint8_t*) ); temp = realloc( program->pmt_packets, (program->num_queued_pmt-1) * sizeof(uint8_t*) ); - if( !temp ) - { - fprintf( stderr, "malloc failed\n" ); - return -1; - } program->pmt_packets = temp; program->num_queued_pmt--; From e40bae8cb42727283086b0b6bc883467aa699131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Carr=C3=A9?= Date: Wed, 8 Aug 2018 11:02:27 +0200 Subject: [PATCH 21/27] SDT: fix UTF-8 strings Bytes above 0x80 would be written as negative --- dvb/dvb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dvb/dvb.c b/dvb/dvb.c index 8a430c0..c429514 100644 --- a/dvb/dvb.c +++ b/dvb/dvb.c @@ -127,11 +127,11 @@ static void write_service_descriptor( bs_t *s, int service_type, char *provider_ bs_write( s, 8, provider_name_length ); // service_provider_name_length while( *provider_name != '\0' ) - bs_write( s, 8, *provider_name++ ); + bs_write( s, 8, (unsigned char)*provider_name++ ); bs_write( s, 8, service_name_length ); // service_name_length while( *service_name != '\0' ) - bs_write( s, 8, *service_name++ ); + bs_write( s, 8, (unsigned char)*service_name++ ); } /* DVB Service Information */ From 0e03d83428d52eeaa8e44bd8fc3797edf183af49 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Tue, 26 Mar 2019 20:29:10 +0000 Subject: [PATCH 22/27] Add low latency mode --- common.h | 1 + libmpegts.c | 38 ++++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/common.h b/common.h index 1e1be73..c06e99a 100644 --- a/common.h +++ b/common.h @@ -295,6 +295,7 @@ struct ts_writer_t int cbr; int ts_muxrate; + int lowlatency; int pat_cc; diff --git a/libmpegts.c b/libmpegts.c index b7490aa..9080bd7 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1693,7 +1693,7 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t new_pes[i]->header_size = write_pes( w, program, &frames[i], new_pes[i] ); } - if( !initial_queued_pes ) + if( !w->lowlatency && !initial_queued_pes ) { out = NULL; *len = 0; @@ -1711,24 +1711,38 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t w->first_input = 1; } - /* loop through and find the time when the second video packet in the queue can arrive */ + int video_found = 0; int64_t pcr_stop = 0; cur_pcr = get_pcr_int( w, 0 ); - for( int i = 0; i < w->num_buffered_frames; i++ ) + if( w->lowlatency ) { - stream = queued_pes[i]->stream; - if( IS_VIDEO( stream ) ) + /* Find the latest arrival time in the batch of packets delivered */ + for( int i = 0; i < w->num_buffered_frames; i++ ) { - /* last frame is a special case - FIXME: is this acceptable in all use-cases? */ - if( !num_frames ) - pcr_stop = queued_pes[i]->dts; - else if( !video_found ) - video_found = 1; - else - pcr_stop = queued_pes[i]->initial_arrival_time; /* earliest that a frame can arrive */ + stream = queued_pes[i]->stream; + if( queued_pes[i]->final_arrival_time > pcr_stop ) + pcr_stop = queued_pes[i]->final_arrival_time; + } + } + else + { + /* loop through and find the time when the second video packet in the queue can arrive */ + for( int i = 0; i < w->num_buffered_frames; i++ ) + { + stream = queued_pes[i]->stream; + if( IS_VIDEO( stream ) ) + { + /* last frame is a special case - FIXME: is this acceptable in all use-cases? */ + if( !num_frames ) + pcr_stop = queued_pes[i]->dts; + else if( !video_found ) + video_found = 1; + else + pcr_stop = queued_pes[i]->initial_arrival_time; /* earliest that a frame can arrive */ + } } } From 43f4dd76b0d6ed2e825e3c3febd6b52bcffa60f7 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Tue, 26 Mar 2019 20:34:59 +0000 Subject: [PATCH 23/27] Expose lowlatency to API --- libmpegts.c | 1 + libmpegts.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libmpegts.c b/libmpegts.c index 9080bd7..36c594a 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -886,6 +886,7 @@ static void update_ts_params( ts_writer_t *w, ts_main_t *params ) w->ts_muxrate = params->muxrate; w->cbr = params->cbr; w->legacy_constraints = params->legacy_constraints; + w->lowlatency = params->lowlatency; w->pcr_period = params->pcr_period ? params->pcr_period : PCR_MAX_RETRANS_TIME; w->pat_period = params->pat_period ? params->pat_period : PAT_MAX_RETRANS_TIME; diff --git a/libmpegts.h b/libmpegts.h index 5274c23..3f5f8af 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -315,6 +315,7 @@ typedef struct ts_main_t int muxrate; int cbr; int ts_type; + int lowlatency; int network_pid; From 3355e7dde607192ad1b959172c96654ebbf8a6cf Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Tue, 30 Jul 2019 14:38:45 +0100 Subject: [PATCH 24/27] Fix typo --- libmpegts.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libmpegts.c b/libmpegts.c index 36c594a..1466725 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -29,7 +29,7 @@ #include "crc/crc.h" #include -static const int steam_type_table[29][2] = +static const int stream_type_table[29][2] = { { LIBMPEGTS_VIDEO_MPEG2, VIDEO_MPEG2 }, { LIBMPEGTS_VIDEO_AVC, VIDEO_AVC }, @@ -1010,16 +1010,16 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) cur_stream->pid = stream_in->pid; cur_stream->stream_format = stream_in->stream_format; - for( int j = 0; steam_type_table[j][0] != 0; j++ ) + for( int j = 0; stream_type_table[j][0] != 0; j++ ) { - if( cur_stream->stream_format == steam_type_table[j][0] ) + if( cur_stream->stream_format == stream_type_table[j][0] ) { /* DVB AC-3 and EAC-3 are different */ if( w->ts_type == TS_TYPE_DVB && ( cur_stream->stream_format == LIBMPEGTS_AUDIO_AC3 || cur_stream->stream_format == LIBMPEGTS_AUDIO_EAC3 ) ) j++; - cur_stream->stream_type = steam_type_table[j][1]; + cur_stream->stream_type = stream_type_table[j][1]; break; } } From 3a8b94f844f59fa0edc24ad2db2c8f87575a451e Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 3 Aug 2019 09:19:34 +0100 Subject: [PATCH 25/27] Add SCTE-35 support --- cablelabs/cablelabs.c | 7 ++++++ cablelabs/cablelabs.h | 2 ++ common.h | 2 ++ libmpegts.c | 52 ++++++++++++++++++++++++++++++++++++------- libmpegts.h | 1 + 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/cablelabs/cablelabs.c b/cablelabs/cablelabs.c index 677d43f..afe86f8 100644 --- a/cablelabs/cablelabs.c +++ b/cablelabs/cablelabs.c @@ -38,3 +38,10 @@ void write_scte_adaptation_descriptor( bs_t *s ) bs_write( s, 8, SCTE_ADAPTATION_FIELD_DESCRIPTOR_TAG ); // descriptor_tag bs_write( s, 8, 0 ); // descriptor_length } + +void write_scte35_cue_identifier_descriptor( bs_t *s ) +{ + bs_write( s, 8, SCTE35_CUE_IDENTIFIER_DESCRIPTOR_TAG ); // descriptor_tag + bs_write( s, 8, 1 ); // descriptor_length + bs_write( s, 8, 0 ); // cue_stream_type +} \ No newline at end of file diff --git a/cablelabs/cablelabs.h b/cablelabs/cablelabs.h index 5a8986a..267f20c 100644 --- a/cablelabs/cablelabs.h +++ b/cablelabs/cablelabs.h @@ -24,8 +24,10 @@ /* Descriptors */ #define SCTE_ADAPTATION_FIELD_DESCRIPTOR_TAG 0x97 #define CABLELABS_3D_MPEG2_DESCRIPTOR_TAG 0xe8 +#define SCTE35_CUE_IDENTIFIER_DESCRIPTOR_TAG 0x8a void write_cablelabs_3d_descriptor( bs_t *s ); void write_scte_adaptation_descriptor( bs_t *s ); +void write_scte35_cue_identifier_descriptor( bs_t *s ); #endif diff --git a/common.h b/common.h index c06e99a..19a0a90 100644 --- a/common.h +++ b/common.h @@ -44,6 +44,8 @@ #define PRIVATE_SECTION 0x05 #define PRIVATE_DATA 0x06 +#define DATA_SCTE35 0x86 + #define TS_HEADER_SIZE 4 #define TS_PACKET_SIZE 188 #define TS_CLOCK 27000000LL diff --git a/libmpegts.c b/libmpegts.c index 1466725..8ffd84a 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -29,7 +29,7 @@ #include "crc/crc.h" #include -static const int stream_type_table[29][2] = +static const int stream_type_table[30][2] = { { LIBMPEGTS_VIDEO_MPEG2, VIDEO_MPEG2 }, { LIBMPEGTS_VIDEO_AVC, VIDEO_AVC }, @@ -59,6 +59,7 @@ static const int stream_type_table[29][2] = { LIBMPEGTS_ANCILLARY_RDD11, PRIVATE_DATA }, { LIBMPEGTS_ANCILLARY_2038, PRIVATE_DATA }, { LIBMPEGTS_AUDIO_OPUS, PRIVATE_DATA }, + { LIBMPEGTS_DATA_SCTE35, DATA_SCTE35 }, { 0 }, }; @@ -478,6 +479,14 @@ static int write_pmt( ts_writer_t *w, ts_int_program_t *program ) else if( w->ts_type == TS_TYPE_BLU_RAY ) write_registration_descriptor( &q, REGISTRATION_DESCRIPTOR_TAG, 4, "HDMV" ); + for( int i = 0; i < program->num_streams; i++ ) + { + ts_int_stream_t *stream = program->streams[i]; + + if( stream->stream_format == LIBMPEGTS_DATA_SCTE35 ) + write_registration_descriptor( &q, REGISTRATION_DESCRIPTOR_TAG, 4, "CUEI" ); + } + /* Optional descriptor(s) here */ bs_flush( &q ); @@ -496,7 +505,7 @@ static int write_pmt( ts_writer_t *w, ts_int_program_t *program ) /* reset temporary bitstream context for streams loop */ bs_init( &q, temp1, 512 ); - if( stream->stream_format != LIBMPEGTS_ANCILLARY_RDD11 ) + if( stream->stream_format != LIBMPEGTS_ANCILLARY_RDD11 && stream->stream_format != LIBMPEGTS_DATA_SCTE35 ) write_data_stream_alignment_descriptor( &q ); if( stream->dvb_au ) @@ -577,6 +586,8 @@ static int write_pmt( ts_writer_t *w, ts_int_program_t *program ) write_registration_descriptor( &q, REGISTRATION_DESCRIPTOR_TAG, 4, "Opus" ); write_opus_descriptor( &q, stream ); } + else if( stream->stream_format == LIBMPEGTS_DATA_SCTE35 ) + write_scte35_cue_identifier_descriptor( &q ); // TODO other stream_type descriptors @@ -1653,7 +1664,7 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t new_pes[i]->write_pulldown_info = frames[i].write_pulldown_info; new_pes[i]->pic_struct = frames[i].pic_struct; } - else if( stream->stream_format == LIBMPEGTS_AUDIO_302M ) + else if( stream->stream_format == LIBMPEGTS_AUDIO_302M || stream->stream_format == LIBMPEGTS_DATA_SCTE35 ) new_pes[i]->initial_arrival_time = (new_pes[i]->dts * 300) - frames[i].duration; else if( stream->stream_format == LIBMPEGTS_DVB_TELETEXT ) new_pes[i]->initial_arrival_time = (new_pes[i]->dts - 3600) * 300; /* Teletext is special because data can only stay in the buffer for 40ms */ @@ -1691,7 +1702,19 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t return -1; } - new_pes[i]->header_size = write_pes( w, program, &frames[i], new_pes[i] ); + /* Not technically a PES but put it through the same codepath */ + if ( stream->stream_format == LIBMPEGTS_DATA_SCTE35 ) + { + new_pes[i]->data[0] = 0; // pointer_field + memcpy( new_pes[i]->data+1, frames[i].data, frames[i].size ); + new_pes[i]->size = new_pes[i]->bytes_left = frames[i].size + 1; + new_pes[i]->cur_pos = new_pes[i]->data; + new_pes[i]->header_size = 0; + } + else + { + new_pes[i]->header_size = write_pes( w, program, &frames[i], new_pes[i] ); + } } if( !w->lowlatency && !initial_queued_pes ) @@ -1713,7 +1736,7 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t } - int video_found = 0; + int video_found = 0, start = 0; int64_t pcr_stop = 0; cur_pcr = get_pcr_int( w, 0 ); @@ -1891,7 +1914,12 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t /* special case where the adaptation_field_length byte is the stuffing */ // FIXME except for cablelabs legacy - if( stuffing == 1 && !adapt_field_len ) + + if( stream->stream_format == LIBMPEGTS_DATA_SCTE35 ) + { + adapt_field_len = 0; /* Theoretically could be made PCR */ + } + else if( stuffing == 1 && !adapt_field_len ) { stuffing = flags = 0; adapt_field_len = 1; @@ -1902,11 +1930,15 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t stuffing -= 2; /* 2 bytes for adaptation field in this case. NOTE: needs fixing if more private data added */ } + start = bs_pos( s ); write_packet_header( w, s, pes_start, stream->pid, PAYLOAD_ONLY + ((!!adapt_field_len)<<1), &stream->cc ); if( adapt_field_len ) write_adaptation_field( w, s, program, pes, write_pcr, flags, stuffing, 0 ); - write_bytes(s, pes->cur_pos, pes->bytes_left ); + write_bytes( s, pes->cur_pos, pes->bytes_left ); + if( stream->stream_format == LIBMPEGTS_DATA_SCTE35 ) + write_padding( s, start ); + pes->bytes_left = 0; add_to_buffer( &stream->tb ); if( increase_pcr( w, 1, 0 ) < 0 ) @@ -2086,7 +2118,11 @@ int increase_pcr( ts_writer_t *w, int num_packets, int imaginary ) drip_buffer( w, program, w->rx_sys, &w->tb, next_pcr ); for( int i = 0; i < program->num_streams; i++ ) { - drip_buffer( w, program, program->streams[i]->rx, &program->streams[i]->tb, next_pcr ); + /* SCTE35 is PSI so not part of T-STD */ + if( program->streams[i]->stream_format == LIBMPEGTS_DATA_SCTE35 ) + program->streams[i]->tb.cur_buf = 0; + else + drip_buffer( w, program, program->streams[i]->rx, &program->streams[i]->tb, next_pcr ); } w->packets_written += num_packets; diff --git a/libmpegts.h b/libmpegts.h index 3f5f8af..ea644a8 100644 --- a/libmpegts.h +++ b/libmpegts.h @@ -71,6 +71,7 @@ /* Misc */ #define LIBMPEGTS_AUDIO_OPUS 160 +#define LIBMPEGTS_DATA_SCTE35 161 /**** Stream IDs ****/ /* SMPTE 302M, AC3, DVB subtitles and Teletext use Private Stream 1 */ From dd417442651535ea893e413192660d5c0aac7f8b Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Sat, 30 Jan 2021 19:22:26 +0100 Subject: [PATCH 26/27] anc/smpte2038: Add muxing parameters --- libmpegts.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libmpegts.c b/libmpegts.c index 3848299..ca43897 100644 --- a/libmpegts.c +++ b/libmpegts.c @@ -1108,6 +1108,10 @@ int ts_setup_transport_stream( ts_writer_t *w, ts_main_t *params ) cur_stream->rx = bitrate; cur_stream->rbx = bitrate; } + else if( cur_stream->stream_format == LIBMPEGTS_ANCILLARY_2038 ) + { + cur_stream->rx = 1.2 * 2500000; + } cur_program->streams[cur_program->num_streams] = cur_stream; cur_program->num_streams++; @@ -1663,7 +1667,7 @@ int ts_write_frames( ts_writer_t *w, ts_frame_t *frames, int num_frames, uint8_t new_pes[i]->write_pulldown_info = frames[i].write_pulldown_info; new_pes[i]->pic_struct = frames[i].pic_struct; } - else if( stream->stream_format == LIBMPEGTS_AUDIO_302M || stream->stream_format == LIBMPEGTS_DATA_SCTE35 ) + else if( stream->stream_format == LIBMPEGTS_AUDIO_302M || stream->stream_format == LIBMPEGTS_DATA_SCTE35 || stream->stream_format == LIBMPEGTS_ANCILLARY_2038 ) new_pes[i]->initial_arrival_time = (new_pes[i]->dts * 300) - frames[i].duration; else if( stream->stream_format == LIBMPEGTS_DVB_TELETEXT ) new_pes[i]->initial_arrival_time = (new_pes[i]->dts - 3600) * 300; /* Teletext is special because data can only stay in the buffer for 40ms */ From 4c363f5da0910e1fdef3918172a1f2e07f7d6793 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Fri, 10 Sep 2021 21:59:35 +0100 Subject: [PATCH 27/27] dvb: Write correct magazine number --- dvb/dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dvb/dvb.c b/dvb/dvb.c index c429514..575cd73 100644 --- a/dvb/dvb.c +++ b/dvb/dvb.c @@ -80,7 +80,7 @@ void write_teletext_descriptor( bs_t *s, ts_int_stream_t *stream, int vbi ) for( int j = 0; j < 3; j++ ) bs_write( s, 8, teletext->lang_code[j] ); // ISO_639_language_code bs_write( s, 5, teletext->teletext_type ); // teletext_type - bs_write( s, 3, teletext->teletext_magazine_number ); // teletext_magazine_number + bs_write( s, 3, teletext->teletext_magazine_number == 8 ? 0 : teletext->teletext_magazine_number ); // teletext_magazine_number bs_write( s, 8, teletext->teletext_page_number ); // teletext_page_number } }