Fixed DVB multiprogram.

This commit is contained in:
AlexBratosin2001 2017-01-13 23:35:34 +02:00
parent ade11eb80f
commit 462f63a294
13 changed files with 345 additions and 156 deletions

View File

@ -11,6 +11,7 @@ made to reuse, not duplicate, as many functions as possible */
#include "ccx_decoders_608.h"
#include "ccx_decoders_708.h"
#include "ccx_decoders_xds.h"
#include "ccx_decoders_vbi.h"
#include "ccx_dtvcc.h"
@ -220,8 +221,8 @@ void dinit_cc_decode(struct lib_cc_decode **ctx)
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_1);
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_2);
dinit_timing_ctx(&lctx->timing);
freep(&lctx->prev);
freep(&lctx->dec_sub.prev);
free_decoder_context(lctx->prev);
free_subtitle(lctx->dec_sub.prev);
freep(ctx);
}
@ -412,3 +413,154 @@ void flush_cc_decode(struct lib_cc_decode *ctx, struct cc_subtitle *sub)
}
}
}
struct encoder_ctx* copy_encoder_context(struct encoder_ctx *ctx)
{
struct encoder_ctx *ctx_copy = NULL;
ctx_copy = malloc(sizeof(struct encoder_ctx));
memcpy(ctx_copy, ctx, sizeof(struct encoder_ctx));
if (ctx->buffer)
{
ctx_copy->buffer = malloc(ctx->capacity * sizeof(unsigned char));
memcpy(ctx_copy->buffer, ctx->buffer, ctx->capacity * sizeof(unsigned char));
}
if (ctx->first_input_file)
{
ctx_copy->first_input_file = malloc(strlen(ctx->first_input_file) * sizeof(char));
memcpy(ctx_copy->first_input_file, ctx->first_input_file, strlen(ctx->first_input_file) * sizeof(char));
}
if (ctx->out)
{
ctx_copy->out = malloc(sizeof(struct ccx_s_write));
memcpy(ctx_copy->out, ctx->out, sizeof(struct ccx_s_write));
}
if (ctx->timing)
{
ctx_copy->timing = malloc(sizeof(struct ccx_common_timing_ctx));
memcpy(ctx_copy->timing, ctx->timing, sizeof(struct ccx_common_timing_ctx));
}
if (ctx->transcript_settings)
{
ctx_copy->transcript_settings = malloc(sizeof(struct ccx_encoders_transcript_format));
memcpy(ctx_copy->transcript_settings, ctx->transcript_settings, sizeof(struct ccx_encoders_transcript_format));
}
if (ctx->subline)
{
ctx_copy->subline = malloc(SUBLINESIZE);
memcpy(ctx_copy->subline, ctx->subline, SUBLINESIZE);
}
if (ctx->start_credits_text)
{
ctx_copy->start_credits_text = malloc(strlen(ctx->start_credits_text) * sizeof(char));
memcpy(ctx_copy->start_credits_text, ctx->start_credits_text, (strlen(ctx->start_credits_text) + 1) * sizeof(char));
}
if (ctx->end_credits_text)
{
ctx_copy->end_credits_text = malloc(strlen(ctx->end_credits_text) * sizeof(char));
memcpy(ctx_copy->end_credits_text, ctx->end_credits_text, (strlen(ctx->end_credits_text) + 1) * sizeof(char));
}
if (ctx->sbs_buffer)
{
ctx_copy->sbs_buffer = malloc((strlen(ctx->sbs_buffer) + 2) * sizeof(unsigned char));
memcpy(ctx_copy->sbs_buffer, ctx->sbs_buffer, (strlen(ctx->sbs_buffer) + 2) * sizeof(unsigned char));
}
return ctx_copy;
}
struct lib_cc_decode* copy_decoder_context(struct lib_cc_decode *ctx)
{
struct lib_cc_decode *ctx_copy = NULL;
ctx_copy = malloc(sizeof(struct lib_cc_decode));
memcpy(ctx_copy, ctx, sizeof(struct lib_cc_decode));
if (ctx->context_cc608_field_1)
{
ctx_copy->context_cc608_field_1 = malloc(sizeof(struct ccx_decoder_608_context));
memcpy(ctx_copy->context_cc608_field_1, ctx->context_cc608_field_1, sizeof(struct ccx_decoder_608_context));
}
if (ctx->context_cc608_field_2)
{
ctx_copy->context_cc608_field_2 = malloc(sizeof(struct ccx_decoder_608_context));
memcpy(ctx_copy->context_cc608_field_2, ctx->context_cc608_field_2, sizeof(struct ccx_decoder_608_context));
}
if (ctx->timing)
{
ctx_copy->timing = malloc(sizeof(struct ccx_common_timing_ctx));
memcpy(ctx_copy->timing, ctx->timing, sizeof(struct ccx_common_timing_ctx));
}
if (ctx->avc_ctx)
{
ctx_copy->avc_ctx = malloc(sizeof(struct avc_ctx));
memcpy(ctx_copy->avc_ctx, ctx->avc_ctx, sizeof(struct avc_ctx));
}
ctx_copy->private_data = NULL;
if (ctx->dtvcc)
{
ctx_copy->dtvcc = malloc(sizeof(struct ccx_dtvcc_ctx));
memcpy(ctx_copy->dtvcc, ctx->dtvcc, sizeof(struct ccx_dtvcc_ctx));
}
if (ctx->xds_ctx)
{
ctx_copy->xds_ctx = malloc(sizeof(struct ccx_decoders_xds_context));
memcpy(ctx_copy->xds_ctx, ctx->xds_ctx, sizeof(struct ccx_decoders_xds_context));
}
if (ctx->vbi_decoder)
{
ctx_copy->vbi_decoder = malloc(sizeof(struct ccx_decoder_vbi_ctx));
memcpy(ctx_copy->vbi_decoder, ctx->vbi_decoder, sizeof(struct ccx_decoder_vbi_ctx));
}
return ctx_copy;
}
struct cc_subtitle* copy_subtitle(struct cc_subtitle *sub)
{
struct cc_subtitle *sub_copy = NULL;
sub_copy = malloc(sizeof(struct cc_subtitle));
memcpy(sub_copy, sub, sizeof(struct cc_subtitle));
if (sub->data)
{
sub_copy->data = malloc(sizeof(struct eia608_screen));
sub_copy->data = malloc(sub->nb_data * sizeof(struct eia608_screen));
memcpy(sub_copy->data, sub->data, sub->nb_data * sizeof(struct eia608_screen));
}
return sub_copy;
}
void free_encoder_context(struct encoder_ctx *ctx)
{
if (!ctx)
return;
freep(&ctx->first_input_file);
freep(&ctx->buffer);
freep(&ctx->out);
freep(&ctx->timing);
freep(&ctx->transcript_settings);
freep(&ctx->subline);
freep(&ctx->start_credits_text);
freep(&ctx->end_credits_text);
freep(&ctx->sbs_buffer);
freep(&ctx->prev);
freep(&ctx);
}
void free_decoder_context(struct lib_cc_decode *ctx)
{
if (!ctx)
return;
freep(&ctx->context_cc608_field_1);
freep(&ctx->context_cc608_field_2);
freep(&ctx->timing);
freep(&ctx->avc_ctx);
freep(&ctx->private_data);
freep(&ctx->dtvcc);
freep(&ctx->xds_ctx);
freep(&ctx->vbi_decoder);
freep(&ctx);
}
void free_subtitle(struct cc_subtitle* sub)
{
if (!sub)
return;
freep(&sub->data);
freep(&sub);
}

View File

@ -25,4 +25,10 @@ void printdata (struct lib_cc_decode *ctx, const unsigned char *data1, int lengt
struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *setting);
void dinit_cc_decode(struct lib_cc_decode **ctx);
void flush_cc_decode(struct lib_cc_decode *ctx, struct cc_subtitle *sub);
struct encoder_ctx* copy_encoder_context(struct encoder_ctx *ctx);
struct lib_cc_decode* copy_decoder_context(struct lib_cc_decode *ctx);
struct cc_subtitle* copy_subtitle(struct cc_subtitle *sub);
void free_encoder_context(struct encoder_ctx *ctx);
void free_decoder_context(struct lib_cc_decode *ctx);
void free_subtitle(struct cc_subtitle* sub);
#endif

View File

@ -5,6 +5,7 @@
#define VBI_DEBUG
#include "ccx_decoders_structs.h"
#include "ccx_decoders_common.h"
struct ccx_decoder_vbi_cfg
{

View File

@ -79,49 +79,6 @@ static const char *XDSProgramTypes[]=
#define XDS_TYPE_TIME_OF_DAY 1
#define XDS_TYPE_LOCAL_TIME_ZONE 4
#define XDS_TYPE_OUT_OF_BAND_CHANNEL_NUMBER 0x40
#define NUM_XDS_BUFFERS 9 // CEA recommends no more than one level of interleaving. Play it safe
#define NUM_BYTES_PER_PACKET 35 // Class + type (repeated for convenience) + data + zero
struct xds_buffer
{
unsigned in_use;
int xds_class;
int xds_type;
unsigned char bytes[NUM_BYTES_PER_PACKET]; // Class + type (repeated for convenience) + data + zero
unsigned char used_bytes;
} ;
typedef struct ccx_decoders_xds_context
{
// Program Identification Number (Start Time) for current program
int current_xds_min;
int current_xds_hour;
int current_xds_date;
int current_xds_month;
int current_program_type_reported; // No.
int xds_start_time_shown;
int xds_program_length_shown;
char xds_program_description[8][33];
char current_xds_network_name[33];
char current_xds_program_name[33];
char current_xds_call_letters[7];
char current_xds_program_type[33];
struct xds_buffer xds_buffers[NUM_XDS_BUFFERS];
int cur_xds_buffer_idx;
int cur_xds_packet_class;
unsigned char *cur_xds_payload;
int cur_xds_payload_length;
int cur_xds_packet_type;
struct ccx_common_timing_ctx *timing;
unsigned current_ar_start;
unsigned current_ar_end;
int xds_write_to_file; // Set to 1 if XDS data is to be written to file
} ccx_decoders_xds_context_t;
struct ccx_decoders_xds_context *ccx_decoders_xds_init_library(struct ccx_common_timing_ctx *timing, int xds_write_to_file)
{

View File

@ -3,6 +3,9 @@
#include "ccx_decoders_common.h"
#define NUM_BYTES_PER_PACKET 35 // Class + type (repeated for convenience) + data + zero
#define NUM_XDS_BUFFERS 9 // CEA recommends no more than one level of interleaving. Play it safe
struct ccx_decoders_xds_context;
void process_xds_bytes (struct ccx_decoders_xds_context *ctx, const unsigned char hi, int lo);
void do_end_of_xds (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx, unsigned char expected_checksum);
@ -10,4 +13,46 @@ void do_end_of_xds (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ct
struct ccx_decoders_xds_context *ccx_decoders_xds_init_library(struct ccx_common_timing_ctx *timing, int xds_write_to_file);
void xds_cea608_test();
struct xds_buffer
{
unsigned in_use;
int xds_class;
int xds_type;
unsigned char bytes[NUM_BYTES_PER_PACKET]; // Class + type (repeated for convenience) + data + zero
unsigned char used_bytes;
};
typedef struct ccx_decoders_xds_context
{
// Program Identification Number (Start Time) for current program
int current_xds_min;
int current_xds_hour;
int current_xds_date;
int current_xds_month;
int current_program_type_reported; // No.
int xds_start_time_shown;
int xds_program_length_shown;
char xds_program_description[8][33];
char current_xds_network_name[33];
char current_xds_program_name[33];
char current_xds_call_letters[7];
char current_xds_program_type[33];
struct xds_buffer xds_buffers[NUM_XDS_BUFFERS];
int cur_xds_buffer_idx;
int cur_xds_packet_class;
unsigned char *cur_xds_payload;
int cur_xds_payload_length;
int cur_xds_packet_type;
struct ccx_common_timing_ctx *timing;
unsigned current_ar_start;
unsigned current_ar_end;
int xds_write_to_file; // Set to 1 if XDS data is to be written to file
} ccx_decoders_xds_context_t;
#endif

View File

@ -9,9 +9,8 @@ static void ccx_demuxer_reset(struct ccx_demuxer *ctx)
ctx->startbytes_pos=0;
ctx->startbytes_avail=0;
memset (ctx->PIDs_seen, 0, 65536*sizeof (int));
memset(ctx->min_pts, UINT64_MAX, 65536 * sizeof(uint64_t));
memset(ctx->found_stream_ids, 0, MAX_NUM_OF_STREAMIDS * sizeof(uint8_t));
memset(ctx->got_important_streams_min_pts, UINT64_MAX, 3 * sizeof(uint64_t));
memset(ctx->min_pts, UINT64_MAX, MAX_PID * sizeof(uint64_t));
memset(ctx->stream_id_of_each_pid, 0, MAX_PID * sizeof(uint8_t));
memset (ctx->PIDs_programs, 0, 65536*sizeof (struct PMT_entry *));
}

View File

@ -15,6 +15,14 @@
#define TS_PMT_MAP_SIZE 128
#define MAX_PROGRAM 128
#define MAX_PROGRAM_NAME_LEN 128
enum STREAM_TYPE
{
PRIVATE_STREAM_1 = 0,
AUDIO,
VIDEO,
COUNT
};
struct ccx_demux_report
{
unsigned program_cnt;
@ -37,7 +45,7 @@ struct program_info
* -1 pid represent that pcr_pid is not available
*/
int16_t pcr_pid;
LLONG min_pts; //global min_pts for a program (relative to all of its streams)
uint64_t got_important_streams_min_pts[COUNT];
};
struct cap_info
@ -69,13 +77,6 @@ struct cap_info
struct list_head pg_stream;
};
enum STREAM_TYPE
{
PRIVATE_STREAM_1 = 0,
AUDIO,
VIDEO,
COUNT
};
struct ccx_demuxer
{
int m2ts;
@ -116,13 +117,14 @@ struct ccx_demuxer
struct PSI_buffer *PID_buffers[MAX_PSI_PID];
int PIDs_seen[MAX_PID];
uint64_t min_pts[MAX_PID];
uint64_t got_important_streams_min_pts[COUNT]; //0 is pvs1 (private stream 1), 1 is audio and 2 is video
/*51 possible stream ids in total, 0xbd is private stream, 0xbe is padding stream,
0xbf private stream 2, 0xc0 - 0xdf audio, 0xe0 - 0xef video
(stream ids range from 0xbd to 0xef so 0xef - 0xbd + 1 = 51)*/
uint8_t found_stream_ids[MAX_NUM_OF_STREAMIDS];
//uint8_t found_stream_ids[MAX_NUM_OF_STREAMIDS];
uint8_t stream_id_of_each_pid[MAX_PID];
uint64_t min_pts[MAX_PID];
struct PMT_entry *PIDs_programs[MAX_PID];
struct ccx_demux_report freport;

View File

@ -910,11 +910,11 @@ void dinit_encoder(struct encoder_ctx **arg, LLONG current_fts)
write_subtitle_file_footer(ctx, ctx->out + i);
}
free_encoder_context(ctx->prev);
dinit_output_ctx(ctx);
freep(&ctx->subline);
freep(&ctx->buffer);
ctx->capacity = 0;
freep(&ctx->prev);
freep(arg);
}

View File

@ -1654,10 +1654,23 @@ int dvbsub_decode(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, co
enc_ctx->wrote_webvtt_header = 1;
}
}
memcpy(enc_ctx->prev, enc_ctx, sizeof(struct encoder_ctx)); //we save the current encoder context
memcpy(sub->prev, sub, sizeof(struct cc_subtitle)); //we save the current subtitle
memcpy(dec_ctx->prev, dec_ctx, sizeof(struct lib_cc_decode)); //we save the current decoder context
/* copy previous encoder context*/
free_encoder_context(enc_ctx->prev);
enc_ctx->prev = NULL;
enc_ctx->prev = copy_encoder_context(enc_ctx);
/* copy previous decoder context */
free_decoder_context(dec_ctx->prev);
dec_ctx->prev = NULL;
dec_ctx->prev = copy_decoder_context(dec_ctx);
freep(&dec_ctx->prev->private_data);
dec_ctx->prev->private_data = malloc(sizeof(struct DVBSubContext));
memcpy(dec_ctx->prev->private_data, dec_ctx->private_data, sizeof(struct DVBSubContext));
/* copy previous subtitle */
free_subtitle(sub->prev);
sub->prev = NULL;
sub->prev = copy_subtitle(sub);
sub->prev->start_time = (dec_ctx->timing->current_pts - dec_ctx->timing->min_pts) / (MPEG_CLOCK_FREQ / 1000); //we set the start time of the previous sub the current pts
write_dvb_sub(dec_ctx->prev, sub->prev); //we write the current dvb sub to update decoder context
enc_ctx->write_previous = 1; //we update our boolean value so next time the program reaches this block of code, it encodes the previous sub
got_segment |= 16;

View File

@ -809,8 +809,6 @@ int general_loop(struct lib_ccx_ctx *ctx)
int caps = 0;
uint64_t min_pts = UINT64_MAX;
int got_pts = 0;
int set_pts = 0;
stream_mode = ctx->demux_ctx->get_stream_mode(ctx->demux_ctx);
@ -881,37 +879,45 @@ int general_loop(struct lib_ccx_ctx *ctx)
dec_ctx = update_decoder_list_cinfo(ctx, cinfo);
dec_ctx->dtvcc->encoder = (void *)enc_ctx; //WARN: otherwise cea-708 will not work
if (!set_pts && dec_ctx->codec == CCX_CODEC_TELETEXT) //even if there's no sub data, we still need to set the min_pts
if (dec_ctx->timing->min_pts == 0x01FFFFFFFFLL) //if we didn't set the min_pts of the program
{
if (!got_pts && (ctx->demux_ctx->got_important_streams_min_pts[PRIVATE_STREAM_1] != UINT64_MAX || ctx->demux_ctx->got_important_streams_min_pts[AUDIO] != UINT64_MAX || ctx->demux_ctx->got_important_streams_min_pts[VIDEO] != UINT64_MAX)) //it means we got the first pts for either sub, audio or video :)
int p_index = 0; //program index
for (int i = 0; i < ctx->demux_ctx->nb_program; i++)
{
/*we don't need to parse the entire min_pts array since
we are only interested in sub, audio and video stream pts
and we have got_important_streams_min_pts array for that*/
for (int i = 0; i < COUNT; i++)
if (dec_ctx->program_number == ctx->demux_ctx->pinfo[i].program_number)
{
if (ctx->demux_ctx->got_important_streams_min_pts[i] != UINT64_MAX) //PTS is 33 bit, array is 64 so we set the default value to UINT64_MAX instead of 0 because a PTS can also be 0
p_index = i;
break;
}
}
if (dec_ctx->codec == CCX_CODEC_TELETEXT) //even if there's no sub data, we still need to set the min_pts
{
if ((ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[PRIVATE_STREAM_1] != UINT64_MAX || ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[AUDIO] != UINT64_MAX || ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[VIDEO] != UINT64_MAX)) //it means we got the first pts for either sub, audio or video :)
{
/*we don't need to parse the entire min_pts array since
we are only interested in sub, audio and video stream pts
and we have got_important_streams_min_pts array for that*/
for (int i = 0; i < COUNT; i++)
{
//printf("Got pts: %" PRId64 " for PID %d\n", ctx->demux_ctx->min_pts[i], i);
if (ctx->demux_ctx->got_important_streams_min_pts[i] < min_pts)
min_pts = ctx->demux_ctx->got_important_streams_min_pts[i];
if (ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[i] != UINT64_MAX) //PTS is 33 bit, array is 64 so we set the default value to UINT64_MAX instead of 0 because a PTS can also be 0
{
//printf("Got pts: %" PRId64 " for PID %d\n", ctx->demux_ctx->min_pts[i], i);
if (ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[i] < min_pts)
min_pts = ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[i];
}
}
}
ctx->demux_ctx->pinfo->min_pts = min_pts; //we set the program's min_pts (not exactly perfect since we would need to parse the entire min_pts array to get the real min_pts for the program, but for now it's a good approximation)
got_pts = 1;
}
set_pts = 1;
}
if (!set_pts && dec_ctx->codec == CCX_CODEC_DVB) //DVB will always have to be in sync with video (no matter the min_pts of the other streams)
{
if (!got_pts && ctx->demux_ctx->got_important_streams_min_pts[AUDIO] != UINT64_MAX) //it means we got the first pts for video
if (dec_ctx->codec == CCX_CODEC_DVB) //DVB will always have to be in sync with video (no matter the min_pts of the other streams)
{
min_pts = ctx->demux_ctx->got_important_streams_min_pts[AUDIO];
set_current_pts(dec_ctx->timing, min_pts);
set_fts(dec_ctx->timing);
got_pts = 1;
if (ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[AUDIO] != UINT64_MAX) //it means we got the first pts for audio
{
min_pts = ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[AUDIO];
set_current_pts(dec_ctx->timing, min_pts);
set_fts(dec_ctx->timing);
}
}
set_pts = 1;
}
if (enc_ctx)
@ -979,38 +985,46 @@ int general_loop(struct lib_ccx_ctx *ctx)
enc_ctx = update_encoder_list_cinfo(ctx, cinfo);
dec_ctx = update_decoder_list_cinfo(ctx, cinfo);
dec_ctx->dtvcc->encoder = (void *)enc_ctx; //WARN: otherwise cea-708 will not work
if (!set_pts && dec_ctx->codec == CCX_CODEC_TELETEXT) //even if there's no sub data, we still need to set the min_pts
if (dec_ctx->timing->min_pts == 0x01FFFFFFFFLL) //if we didn't set the min_pts of the program
{
if (!got_pts && (ctx->demux_ctx->got_important_streams_min_pts[PRIVATE_STREAM_1] != UINT64_MAX || ctx->demux_ctx->got_important_streams_min_pts[AUDIO] != UINT64_MAX || ctx->demux_ctx->got_important_streams_min_pts[VIDEO] != UINT64_MAX)) //it means we got the first pts for either sub, audio or video :)
int p_index = 0; //program index
for (int i = 0; i < ctx->demux_ctx->nb_program; i++)
{
/*we don't need to parse the entire min_pts array since
we are only interested in sub, audio and video stream pts
and we have got_important_streams_min_pts array for that*/
for (int i = 0; i < COUNT; i++)
if (dec_ctx->program_number == ctx->demux_ctx->pinfo[i].program_number)
{
if (ctx->demux_ctx->got_important_streams_min_pts[i] != UINT64_MAX) //PTS is 33 bit, array is 64 so we set the default value to UINT64_MAX instead of 0 because a PTS can also be 0
p_index = i;
break;
}
}
if (dec_ctx->codec == CCX_CODEC_TELETEXT) //even if there's no sub data, we still need to set the min_pts
{
if ((ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[PRIVATE_STREAM_1] != UINT64_MAX || ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[AUDIO] != UINT64_MAX || ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[VIDEO] != UINT64_MAX)) //it means we got the first pts for either sub, audio or video :)
{
/*we don't need to parse the entire min_pts array since
we are only interested in sub, audio and video stream pts
and we have got_important_streams_min_pts array for that*/
for (int i = 0; i < COUNT; i++)
{
//printf("Got pts: %" PRId64 " for PID %d\n", ctx->demux_ctx->min_pts[i], i);
if (ctx->demux_ctx->got_important_streams_min_pts[i] < min_pts)
min_pts = ctx->demux_ctx->got_important_streams_min_pts[i];
if (ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[i] != UINT64_MAX) //PTS is 33 bit, array is 64 so we set the default value to UINT64_MAX instead of 0 because a PTS can also be 0
{
//printf("Got pts: %" PRId64 " for PID %d\n", ctx->demux_ctx->min_pts[i], i);
if (ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[i] < min_pts)
min_pts = ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[i];
}
}
}
ctx->demux_ctx->pinfo->min_pts = min_pts; //we set the program's min_pts (not exactly perfect since we would need to parse the entire min_pts array to get the real min_pts for the program, but for now it's a good approximation)
got_pts = 1;
}
set_pts = 1;
}
if (!set_pts && dec_ctx->codec == CCX_CODEC_DVB) //DVB will always have to be in sync with video (no matter the min_pts of the other streams)
{
if (!got_pts && ctx->demux_ctx->got_important_streams_min_pts[AUDIO] != UINT64_MAX) //it means we got the first pts for video
if (dec_ctx->codec == CCX_CODEC_DVB) //DVB will always have to be in sync with video (no matter the min_pts of the other streams)
{
min_pts = ctx->demux_ctx->got_important_streams_min_pts[AUDIO];
set_current_pts(dec_ctx->timing, min_pts);
set_fts(dec_ctx->timing);
got_pts = 1;
if (ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[AUDIO] != UINT64_MAX) //it means we got the first pts for audio
{
min_pts = ctx->demux_ctx->pinfo[p_index].got_important_streams_min_pts[AUDIO];
set_current_pts(dec_ctx->timing, min_pts);
set_fts(dec_ctx->timing);
}
}
set_pts = 1;
}
if (enc_ctx)

View File

@ -335,11 +335,7 @@ struct lib_cc_decode *update_decoder_list_cinfo(struct lib_ccx_ctx *ctx, struct
//DVB related
dec_ctx->prev = NULL;
dec_ctx->dec_sub.prev = NULL;
if (dec_ctx->codec == CCX_CODEC_DVB)
{
dec_ctx->prev = malloc(sizeof(struct lib_cc_decode));
dec_ctx->dec_sub.prev = malloc(sizeof(struct cc_subtitle));
}
return dec_ctx;
}
@ -430,13 +426,8 @@ struct encoder_ctx *update_encoder_list_cinfo(struct lib_ccx_ctx *ctx, struct ca
// DVB related
enc_ctx->prev = NULL;
if (cinfo)
{
if (cinfo->codec == CCX_CODEC_DVB)
{
enc_ctx->write_previous = 0;
enc_ctx->prev = malloc(sizeof(struct encoder_ctx));
}
}
freep(&extension);
return enc_ctx;
}

View File

@ -731,8 +731,8 @@ long ts_readstream(struct ccx_demuxer *ctx, struct demuxer_data **data)
memset(&payload, 0, sizeof(payload));
if (ctx->got_important_streams_min_pts[VIDEO] == UINT64_MAX)
ctx->got_important_streams_min_pts[VIDEO] = get_video_min_pts(ctx);
/*if (ctx->got_important_streams_min_pts[VIDEO] == UINT64_MAX)
ctx->got_important_streams_min_pts[VIDEO] = get_video_min_pts(ctx);*/
do
{
@ -805,48 +805,33 @@ long ts_readstream(struct ccx_demuxer *ctx, struct demuxer_data **data)
ctx->PIDs_seen[payload.pid]=2;
ts_buffer_psi_packet(ctx);
if(ctx->PID_buffers[payload.pid]!=NULL && ctx->PID_buffers[payload.pid]->buffer_length>0)
if(parse_PMT(ctx, ctx->PID_buffers[payload.pid]->buffer+1, ctx->PID_buffers[payload.pid]->buffer_length-1, pinfo))
if(parse_PMT(ctx, ctx->PID_buffers[payload.pid]->buffer+1, ctx->PID_buffers[payload.pid]->buffer_length-1, pinfo))
gotpes=1; // Signals that something changed and that we must flush the buffer
continue;
}
//PTS calculation
if (ctx->got_important_streams_min_pts[PRIVATE_STREAM_1] == UINT64_MAX || ctx->got_important_streams_min_pts[AUDIO] == UINT64_MAX || ctx->got_important_streams_min_pts[VIDEO] == UINT64_MAX) //if we didn't already get the first PTS of the important streams
if (payload.pesstart) //if there is PES Header data in the payload and we didn't get the first pts of that stream
{
if (payload.pesstart) //if there is PES Header data in the payload and we didn't get the first pts of that stream
if (ctx->min_pts[payload.pid] == UINT64_MAX) //check if we don't have the min_pts of that packet's pid
{
if (ctx->min_pts[payload.pid] == UINT64_MAX) //check if we don't have the min_pts of that packet's pid
// Packetized Elementary Stream (PES) 32-bit start code
uint64_t pes_prefix = (payload.start[0] << 16) | (payload.start[1] << 8) | payload.start[2];
uint8_t pes_stream_id = payload.start[3];
uint64_t pts = 0;
// check for PES header
if (pes_prefix == 0x000001)
{
// Packetized Elementary Stream (PES) 32-bit start code
uint64_t pes_prefix = (payload.start[0] << 16) | (payload.start[1] << 8) | payload.start[2];
uint8_t pes_stream_id = payload.start[3];
uint64_t pts = 0;
// check for PES header
if (pes_prefix == 0x000001)
{
//if we didn't already have this stream id with its first pts then calculate
if (pes_stream_id != ctx->found_stream_ids[pes_stream_id - 0xbd])
{
pts = get_pts(payload.start);
//keep in mind we already checked if we have this stream id
ctx->found_stream_ids[pes_stream_id - 0xbd] = pes_stream_id; //add it
ctx->min_pts[payload.pid] = pts; //and add its packet pts (we still have this array in case someone wants the global PTS for all stream_id not only for pvs1, audio and video)
/*we already checked if we got that packet's pts
but we still need to check if we got the min_pts of the stream type
because we might have multiple audio streams for example (audio and subs are sent in order)*/
if (pes_stream_id == 0xbd && ctx->got_important_streams_min_pts[PRIVATE_STREAM_1] == UINT64_MAX) //private stream 1
ctx->got_important_streams_min_pts[PRIVATE_STREAM_1] = pts;
if (pes_stream_id >= 0xC0 && pes_stream_id <= 0xDF && ctx->got_important_streams_min_pts[AUDIO] == UINT64_MAX) //audio
ctx->got_important_streams_min_pts[AUDIO] = pts;
}
}
pts = get_pts(payload.start);
//keep in mind we already checked if we have this stream id
ctx->stream_id_of_each_pid[payload.pid] = pes_stream_id;
ctx->min_pts[payload.pid] = pts; //and add its packet pts
}
}
}
switch (ctx->PIDs_seen[payload.pid])
{
case 0: // First time we see this PID
@ -996,6 +981,32 @@ long ts_readstream(struct ccx_demuxer *ctx, struct demuxer_data **data)
}
while( !gotpes ); // gotpes==1 never arrives here because of the breaks
for (int i = 0; i < ctx->nb_program; i++)
{
pinfo = &ctx->pinfo[i];
for (int j = 0; j < MAX_PID; j++)
{
if (ctx->PIDs_programs[j])
{
if (ctx->PIDs_programs[j]->program_number == pinfo->program_number)
{
if (ctx->min_pts[j] != UINT64_MAX)
{
if (ctx->stream_id_of_each_pid[j] == 0xbd)
if (ctx->min_pts[j] < pinfo->got_important_streams_min_pts[PRIVATE_STREAM_1])
pinfo->got_important_streams_min_pts[PRIVATE_STREAM_1] = ctx->min_pts[j];
if (ctx->stream_id_of_each_pid[j] >= 0xc0 && ctx->stream_id_of_each_pid[j] <= 0xdf)
if (ctx->min_pts[j] < pinfo->got_important_streams_min_pts[AUDIO])
pinfo->got_important_streams_min_pts[AUDIO] = ctx->min_pts[j];
if (ctx->stream_id_of_each_pid[j] >= 0xe0 && ctx->stream_id_of_each_pid[j] <= 0xef)
if (ctx->min_pts[j] < pinfo->got_important_streams_min_pts[VIDEO])
pinfo->got_important_streams_min_pts[VIDEO] = ctx->min_pts[j];
}
}
}
}
}
if (ret == CCX_EOF)
{
cinfo_cremation(ctx, data);

View File

@ -74,6 +74,7 @@ int update_pinfo(struct ccx_demuxer *ctx, int pid, int program_number)
ctx->pinfo[ctx->nb_program].analysed_PMT_once = CCX_FALSE;
ctx->pinfo[ctx->nb_program].name[0] = '\0';
ctx->pinfo[ctx->nb_program].pcr_pid = -1;
memset(ctx->pinfo[ctx->nb_program].got_important_streams_min_pts, UINT64_MAX, 3 * sizeof(uint64_t));
ctx->nb_program++;
return CCX_OK;
@ -586,9 +587,6 @@ int parse_PAT (struct ccx_demuxer *ctx)
dinit_cap(ctx);
clear_PMT_array(ctx);
memset (ctx->PIDs_seen,0,sizeof (int) *65536); // Forget all we saw
memset(ctx->min_pts, UINT64_MAX, 65536 * sizeof(uint64_t));
memset(ctx->found_stream_ids, 0, MAX_NUM_OF_STREAMIDS * sizeof(uint8_t));
memset(ctx->got_important_streams_min_pts, UINT64_MAX, 3 * sizeof(uint64_t));
if (!tlt_config.user_page) // If the user didn't select a page...
tlt_config.page=0; // ..forget whatever we detected.