From 029940f3c27aac19a92177fb25a859a117a49940 Mon Sep 17 00:00:00 2001 From: jc44 Date: Thu, 3 Dec 2009 12:04:12 +0000 Subject: [PATCH] Added max bitrate calculation code to buffering report --HG-- extra : convert_revision : svn%3Aeff31bef-be4a-0410-a8fe-e47997df2690/trunk%40152 --- tsreport.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/tsreport.c b/tsreport.c index b648640..1de8398 100644 --- a/tsreport.c +++ b/tsreport.c @@ -77,6 +77,21 @@ struct diff_from_pcr unsigned int num; // the number of TS records compared }; +typedef struct avg_rate_elss +{ + uint64_t time; + uint64_t bytes; +} avg_rate_el_t; + +typedef struct avg_ratess +{ + unsigned int max_els; + unsigned int in_el; + unsigned int out_el; + avg_rate_el_t * els; + uint64_t max_rate; +} avg_rate_t; + struct stream_data { uint32_t pid; int stream_type; @@ -92,6 +107,7 @@ struct stream_data { // PTS/DTS in the file, when we're finishing up uint64_t pts; uint64_t dts; + uint64_t pcr; int err_pts_lt_dts; int err_dts_lt_prev_dts; @@ -103,6 +119,11 @@ struct stream_data { struct diff_from_pcr pcr_dts_diff; int pts_ne_dts; + + int pcr_seen; + uint64_t first_pcr; + uint64_t ts_bytes; + avg_rate_t rate; }; static int pid_index(struct stream_data *data, @@ -116,6 +137,59 @@ static int pid_index(struct stream_data *data, return -1; } +// (x - y) with allowance for PCR wrap - unsigned version +static uint64_t +pcr_unsigned_diff(uint64_t x, uint64_t y) +{ + return x > y ? x - y : + 300ULL * (1ULL << 33) - (y - x); +} + +unsigned int +avg_rate_inc(avg_rate_t * ar, unsigned int n) +{ + return n + 1 >= ar->max_els ? 0 : n + 1; +} + +static void +avg_rate_add(avg_rate_t * ar, uint64_t time, uint64_t bytes) +{ + uint64_t gap = 27000000 / 2; // 0.5 sec + uint64_t delta_b; + uint64_t delta_t; + uint64_t rate; + + if (ar->els == NULL) + { + ar->max_els = 1024; + ar->els = calloc(ar->max_els, sizeof(ar->els[0])); + } + + while (ar->in_el != ar->out_el && pcr_unsigned_diff(time, ar->els[ar->out_el].time) > gap) + { + ar->out_el = avg_rate_inc(ar, ar->out_el); + } + + ar->els[ar->in_el].time = time; + ar->els[ar->in_el].bytes = bytes; + + delta_b = bytes - ar->els[ar->out_el].bytes; + delta_t = pcr_unsigned_diff(time, ar->els[ar->out_el].time); + + if (delta_t != 0) + { + rate = (delta_b * 8LL * 27000000LL) / delta_t; + if (rate > ar->max_rate) + { + ar->max_rate = rate; + } + } + + ar->in_el = avg_rate_inc(ar, ar->in_el); +} + + + /* * Report on the given file * @@ -178,6 +252,7 @@ static int report_buffering_stats(TS_reader_p tsreader, stats[ii].pcr_dts_diff.min = LONG_MAX; stats[ii].pcr_pts_diff.max = LONG_MIN; stats[ii].pcr_dts_diff.max = LONG_MIN; + stats[ii].first_pcr = ~(uint64_t)0; stats[ii].last_cc = -1; } predict.min_pcr_error = LONG_MAX; @@ -355,6 +430,14 @@ static int report_buffering_stats(TS_reader_p tsreader, predict.prev_pcr = adapt_pcr; predict.prev_pcr_posn = posn; } + + { + int i; + for (i = 0; i != num_streams; ++i) + { + stats[i].pcr_seen = TRUE; + } + } } // end of working with a PCR PID packet // ======================================================================== @@ -405,6 +488,19 @@ static int report_buffering_stats(TS_reader_p tsreader, stats[index].last_cc = cc; } + if (index != -1) + { + if (stats[index].pcr_seen) + { + stats[index].pcr_seen = FALSE; + avg_rate_add(&stats[index].rate, acc_pcr, stats[index].ts_bytes); + } + if (stats[index].first_pcr == ~(uint64_t)0) + stats[index].first_pcr = acc_pcr; + stats[index].pcr = acc_pcr; + stats[index].ts_bytes += 188; + } + if (index != -1 && payload && payload_unit_start_indicator) { // We are the start of a PES packet @@ -648,6 +744,13 @@ static int report_buffering_stats(TS_reader_p tsreader, fmtx_timestamp(stats[ii].first_dts, tfmt_abs), fmtx_timestamp(stats[ii].dts, tfmt_abs)); + { + // Calculate rate over the range of PCRs seen in this stream + uint64_t avg = stats[ii].pcr == stats[ii].first_pcr ? 0LL : + ((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].err_cc_error != 0) fprint_msg(" ### CC error * %d\n", stats[ii].err_cc_error); if (stats[ii].err_cc_dup_error != 0) @@ -1031,7 +1134,8 @@ static void print_usage() "Buffering information:\n" " -buffering, -b Report on the differences between PCR and PTS, and\n" " between PCR and DTS. This is relevant to the size of\n" - " buffers needed in the decoder.\n" + " buffers needed in the decoder. Also reports bitrates;\n" + " the max bitrate is calculated over 0.5sec\n" " -o Output CSV data for -buffering to the named file.\n" " -32 Truncate 33 bit values in the CSV output to 32 bits\n" " (losing the top bit).\n"