kopia lustrzana https://github.com/F5OEO/tstools
Fix CC error reporting to only report things that are actual errors. Previously
tsreport would flag any non-sequential CC numbers as bad, howvever H.222 states that CC should only increment if the TS packet has a payload. If we do have identical CCs tsreport now checks that the contents are identical too. Fixed some warnings where long long != int64_tissue20
rodzic
1c0dda5d6b
commit
60fd634d9b
|
@ -113,6 +113,7 @@ typedef uint8_t byte;
|
|||
// do both, here, for safety.
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
typedef off_t offset_t;
|
||||
|
||||
#if defined(__linux__) && !defined(__USE_FILE_OFFSET64)
|
||||
|
@ -124,14 +125,14 @@ typedef off_t offset_t;
|
|||
#else
|
||||
// On Unices, printf supports %lld for 64 bit integers, and this is suitable
|
||||
// for printing out offset_t when it is 64 bit
|
||||
#define OFFSET_T_FORMAT "%lld"
|
||||
#define OFFSET_T_FORMAT_08 "%08lld" // deprecated, because it looks like hex/octal
|
||||
#define OFFSET_T_FORMAT_8 "%8lld"
|
||||
#define OFFSET_T_FORMAT "%" PRIi64
|
||||
#define OFFSET_T_FORMAT_08 "%08" PRIi64 // deprecated, because it looks like hex/octal
|
||||
#define OFFSET_T_FORMAT_8 "%8" PRIi64
|
||||
#endif
|
||||
|
||||
// Whilst we're at it, define the format for a 64 bit integer as such
|
||||
#define LLD_FORMAT "%lld"
|
||||
#define LLU_FORMAT "%llu"
|
||||
#define LLD_FORMAT "%" PRId64
|
||||
#define LLU_FORMAT "%" PRIu64
|
||||
#define LLD_FORMAT_STUMP "lld"
|
||||
#define LLU_FORMAT_STUMP "llu"
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ static int extract_packets(int input, FILE * output,
|
|||
{
|
||||
packet_buffer = malloc(sizeof(struct _m2ts_packet_buffer));
|
||||
/***DEBUG***/
|
||||
fprint_msg("Allocated buffer @ 0x%08x\n", (unsigned int)packet_buffer);
|
||||
fprint_msg("Allocated buffer @ %p\n", packet_buffer);
|
||||
if (packet_buffer == NULL)
|
||||
{
|
||||
print_err( "### m2ts2ts: out of memory allocating M2TS packet buffer\n");
|
||||
|
@ -157,8 +157,8 @@ static int extract_packets(int input, FILE * output,
|
|||
// so start at the tail and work to the front
|
||||
p = reorder_buffer_tail;
|
||||
if (p != NULL)
|
||||
fprint_msg("tail timestamp = 0x%08x @ 0x%08x\n",
|
||||
p->timestamp, (unsigned int)p);
|
||||
fprint_msg("tail timestamp = 0x%08x @ %p\n",
|
||||
p->timestamp, p);
|
||||
while (p != NULL && p->timestamp > packet_buffer->timestamp)
|
||||
{
|
||||
p = p->prev;
|
||||
|
|
|
@ -3434,8 +3434,8 @@ extern int find_PTS_DTS_in_PES(byte data[],
|
|||
|
||||
if (data[0] != 0 || data[1] != 0 || data[2] != 1)
|
||||
{
|
||||
fprint_err("### find_PTS_in_PES:"
|
||||
" PES packet start code prefix is %02x %02x %02x, not 00 00 01\n",
|
||||
fprint_err("### find_PTS_DTS_in_PES"
|
||||
": PES packet start code prefix is %02x %02x %02x, not 00 00 01\n",
|
||||
data[0],data[1],data[2]);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -3388,6 +3388,7 @@ extern int find_pmt(TS_reader_p tsreader,
|
|||
*pmt = NULL;
|
||||
|
||||
err = find_pat(tsreader,max,verbose,quiet,&sofar,&prog_list);
|
||||
|
||||
if (err == EOF)
|
||||
{
|
||||
if (!quiet) print_msg("No PAT found\n");
|
||||
|
|
|
@ -238,7 +238,7 @@ static int find_PCR_PID(TS_reader_p tsreader,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pid == 0x0000)
|
||||
if (pid == 0x0000 && !got_PAT)
|
||||
{
|
||||
if (!quiet) fprint_msg("Packet %d is PAT\n",count);
|
||||
if (payload_unit_start_indicator && pat_data)
|
||||
|
@ -264,7 +264,7 @@ static int find_PCR_PID(TS_reader_p tsreader,
|
|||
fprint_err("### Error %s PAT\n",
|
||||
(payload_unit_start_indicator?"starting new":"continuing"));
|
||||
if (pat_data) free(pat_data);
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do we need more data to complete this PAT?
|
||||
|
@ -275,7 +275,7 @@ static int find_PCR_PID(TS_reader_p tsreader,
|
|||
if (err != 0)
|
||||
{
|
||||
free(pat_data);
|
||||
return err;
|
||||
continue;
|
||||
}
|
||||
if (!quiet)
|
||||
report_pidint_list(prog_list,"Program list","Program",FALSE);
|
||||
|
|
|
@ -114,6 +114,8 @@ struct stream_data {
|
|||
int err_dts_lt_pcr;
|
||||
int err_cc_error;
|
||||
int err_cc_dup_error;
|
||||
int err_cc_contents;
|
||||
int cc_good;
|
||||
|
||||
struct diff_from_pcr pcr_pts_diff;
|
||||
struct diff_from_pcr pcr_dts_diff;
|
||||
|
@ -124,6 +126,8 @@ struct stream_data {
|
|||
uint64_t first_pcr;
|
||||
uint64_t ts_bytes;
|
||||
avg_rate_t rate;
|
||||
|
||||
uint8_t last_pkt[188];
|
||||
};
|
||||
|
||||
static int pid_index(struct stream_data *data,
|
||||
|
@ -235,6 +239,7 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
|
||||
uint32_t pcr_pid;
|
||||
uint64_t first_pcr = 0;
|
||||
offset_t first_pcr_posn = 0;
|
||||
int pmt_at = 0; // in case we don't look for a PMT
|
||||
int index;
|
||||
int ii;
|
||||
|
@ -394,8 +399,8 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
posn,
|
||||
fmtx_timestamp(adapt_pcr, tfmt_abs | FMTX_TS_N_27MHz));
|
||||
if (file)
|
||||
fprintf(file,LLU_FORMAT ",read," LLU_FORMAT ",,,,\n",
|
||||
posn,(adapt_pcr / (int64_t)300) & report_mask);
|
||||
fprintf(file,OFFSET_T_FORMAT ",read," LLU_FORMAT ",,,,\n",
|
||||
posn,(adapt_pcr / (uint64_t)300) & report_mask);
|
||||
|
||||
if (predict.had_a_pcr)
|
||||
{
|
||||
|
@ -425,6 +430,7 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
if (!quiet)
|
||||
fprint_msg("First PCR at " OFFSET_T_FORMAT "\n",posn);
|
||||
first_pcr = adapt_pcr;
|
||||
first_pcr_posn = posn;
|
||||
predict.had_a_pcr = TRUE;
|
||||
}
|
||||
predict.prev_pcr = adapt_pcr;
|
||||
|
@ -447,25 +453,76 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
{
|
||||
// Do continuity counter checking
|
||||
int cc = packet[3] & 15;
|
||||
const int is_discontinuity = (adapt != NULL && (adapt[0] & 0x80) != 0);
|
||||
|
||||
// Log if required
|
||||
if (continuity_cnt_pid == pid)
|
||||
fprintf(file_cnt, "%d%c", cc, cc == 15 ? '\n' : ' ');
|
||||
|
||||
if (stats[index].last_cc > 0)
|
||||
// CC is meant to increment if we have a payload and not if we don't
|
||||
// CC may legitimately 'be wrong' if the discontinuity flag is set
|
||||
|
||||
if (stats[index].last_cc > 0 && !is_discontinuity)
|
||||
{
|
||||
// We are allowed 1 dup packet
|
||||
// *** Could check that it actually is a dup...
|
||||
if (stats[index].last_cc == cc)
|
||||
{
|
||||
if (stats[index].cc_dup_count++ != 0)
|
||||
if (payload)
|
||||
{
|
||||
if (continuity_cnt_pid == pid)
|
||||
fprintf(file_cnt, "[Duplicate error] ");
|
||||
if (stats[index].err_cc_dup_error++ == 0)
|
||||
if (stats[index].cc_dup_count++ != 0)
|
||||
{
|
||||
fprint_msg("### PID(%d): Continuity Counter >1 duplicate %d at " OFFSET_T_FORMAT "\n",
|
||||
stats[index].pid, cc, posn);
|
||||
if (continuity_cnt_pid == pid)
|
||||
fprintf(file_cnt, "[Duplicate error] ");
|
||||
if (stats[index].err_cc_dup_error++ == 0)
|
||||
{
|
||||
fprint_msg("### PID(%d): Continuity Counter >1 duplicate %d at " OFFSET_T_FORMAT "\n",
|
||||
stats[index].pid, cc, posn);
|
||||
}
|
||||
}
|
||||
|
||||
// Whilst everything else must be identical PCR is expected to
|
||||
// change if it is given. If it exists we know where it is.
|
||||
if (!got_pcr ? (memcmp(stats[index].last_pkt, packet, 188) != 0) :
|
||||
(memcmp(stats[index].last_pkt, packet, 6) != 0 ||
|
||||
memcmp(stats[index].last_pkt + 12, packet + 12, 188 - 12) != 0))
|
||||
{
|
||||
if (stats[index].err_cc_contents++ == 0)
|
||||
fprint_msg("### PID(%d): Continuity Counter duplicate %d: non identical contents at " OFFSET_T_FORMAT "\n",
|
||||
stats[index].pid, cc, posn);
|
||||
// Assume that non-identical CC means we had a discontinuity and
|
||||
// therefore let this packet through
|
||||
#if 0
|
||||
{
|
||||
const uint8_t * a = stats[index].last_pkt;
|
||||
const uint8_t * b = packet;
|
||||
int i;
|
||||
|
||||
fprint_msg("CC contents:\n");
|
||||
|
||||
for (i = 0; i < 188; i += 16, a += 16, b += 16)
|
||||
{
|
||||
int j;
|
||||
const int n = min(16, 188 - i);
|
||||
for (j = 0; j < n; ++j)
|
||||
{
|
||||
fprint_msg("%c%02x", a[j] == b[j] ? ' ' : '*', a[j]);
|
||||
}
|
||||
fprint_msg("\n");
|
||||
for (j = 0; j < n; ++j)
|
||||
{
|
||||
fprint_msg("%c%02x", a[j] == b[j] ? ' ' : '*', b[j]);
|
||||
}
|
||||
fprint_msg("\n\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Real redundant TS packet!
|
||||
// Log it and discard
|
||||
++stats[index].cc_good;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -473,19 +530,34 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
{
|
||||
// Otherwise CC must go up by 1 mod 16
|
||||
stats[index].cc_dup_count = 0;
|
||||
if (((stats[index].last_cc + 1) & 15) != cc)
|
||||
if (payload)
|
||||
{
|
||||
if (((stats[index].last_cc + 1) & 15) != cc)
|
||||
{
|
||||
if (continuity_cnt_pid == pid)
|
||||
fprintf(file_cnt, "[Discontinuity] ");
|
||||
if (stats[index].err_cc_error++ == 0)
|
||||
{
|
||||
fprint_msg("### PID(%d): Continuity Counter discontinuity %d->%d at " OFFSET_T_FORMAT "\n",
|
||||
stats[index].pid, stats[index].last_cc, cc, posn);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// CC not the same but it should be
|
||||
if (continuity_cnt_pid == pid)
|
||||
fprintf(file_cnt, "[Discontinuity] ");
|
||||
if (stats[index].err_cc_error++ == 0)
|
||||
{
|
||||
fprint_msg("### PID(%d): Continuity Counter discontinuity %d->%d at " OFFSET_T_FORMAT "\n",
|
||||
fprint_msg("### PID(%d): Continuity Counter discontinuity %d->%d (but no payload) at " OFFSET_T_FORMAT "\n",
|
||||
stats[index].pid, stats[index].last_cc, cc, posn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stats[index].last_cc = cc;
|
||||
memcpy(stats[index].last_pkt, packet, 188);
|
||||
}
|
||||
|
||||
if (index != -1)
|
||||
|
@ -513,9 +585,9 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
&got_pts,&stats[index].pts,&got_dts,&stats[index].dts);
|
||||
if (err)
|
||||
{
|
||||
fprint_err("### Error looking for PTS/DTS in TS packet at "
|
||||
OFFSET_T_FORMAT "\n",posn);
|
||||
return 1;
|
||||
fprint_err("### PID(%d): Error looking for PTS/DTS in TS packet at "
|
||||
OFFSET_T_FORMAT "\n", stats[index].pid, posn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (got_dts && !got_pts)
|
||||
|
@ -606,6 +678,7 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
escr,posn);
|
||||
fprintf(file,LLU_FORMAT,escr & report_mask);
|
||||
}
|
||||
fprintf(file, ",%u", (payload[4] << 8) | payload[5]);
|
||||
fprintf(file,"\n");
|
||||
}
|
||||
|
||||
|
@ -683,6 +756,12 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
fprint_msg("Read %d TS packet%s\n",count,(count==1?"":"s"));
|
||||
if (pmt) free_pmt(&pmt);
|
||||
if (file) fclose(file);
|
||||
if (predict.had_a_pcr && predict.prev_pcr_posn > first_pcr_posn)
|
||||
{
|
||||
// Multiply by 8 at the end to give us a bit more headroom in file size
|
||||
int rate = (int)((predict.prev_pcr_posn - first_pcr_posn) * 27000000LL / (predict.prev_pcr - first_pcr)) * 8;
|
||||
fprint_msg("Overall stream rate=%d bits/sec\n", rate);
|
||||
}
|
||||
|
||||
fprint_msg("Linear PCR prediction errors: min=%s, max=%s\n",
|
||||
fmtx_timestamp(predict.min_pcr_error, tfmt_diff),
|
||||
|
@ -750,9 +829,13 @@ static int report_buffering_stats(TS_reader_p tsreader,
|
|||
((stats[ii].ts_bytes - 188LL) * 8LL * 27000000LL) / (stats[ii].pcr - stats[ii].first_pcr);
|
||||
fprint_msg(" Stream: %llu bytes; rate: avg %llu bits/s, max %llu bits/s\n", stats[ii].ts_bytes, avg, stats[ii].rate.max_rate);
|
||||
}
|
||||
if (stats[ii].cc_good != 0)
|
||||
fprint_msg(" CC redundant packets * %d\n", stats[ii].cc_good);
|
||||
|
||||
if (stats[ii].err_cc_error != 0)
|
||||
fprint_msg(" ### CC error * %d\n", stats[ii].err_cc_error);
|
||||
if (stats[ii].err_cc_contents != 0)
|
||||
fprint_msg(" ### CC contents error * %d\n", stats[ii].err_cc_contents);
|
||||
if (stats[ii].err_cc_dup_error != 0)
|
||||
fprint_msg(" ### CC duplicate error * %d\n", stats[ii].err_cc_dup_error);
|
||||
if (stats[ii].err_pts_lt_dts != 0)
|
||||
|
|
Ładowanie…
Reference in New Issue