kopia lustrzana https://github.com/F5OEO/tstools
pcapreport can now report on disparities between PCR and
recorded packet times. --HG-- extra : convert_revision : svn%3Aeff31bef-be4a-0410-a8fe-e47997df2690/trunk%4054issue20
rodzic
05f19a9139
commit
aa08148c62
390
pcapreport.c
390
pcapreport.c
|
@ -49,6 +49,7 @@
|
|||
#include "ipv4.h"
|
||||
#include "version.h"
|
||||
#include "misc_fns.h"
|
||||
#include "ts_fns.h"
|
||||
|
||||
typedef struct pcapreport_ctx_struct
|
||||
{
|
||||
|
@ -57,14 +58,74 @@ typedef struct pcapreport_ctx_struct
|
|||
int had_input_name;
|
||||
int dump_data;
|
||||
int dump_extra;
|
||||
int time_report;
|
||||
int verbose;
|
||||
PCAP_reader_p pcreader;
|
||||
pcap_hdr_t pcap_hdr;
|
||||
char *output_name;
|
||||
FILE *output_file;
|
||||
uint32_t output_dest_addr;
|
||||
uint32_t output_dest_port;
|
||||
|
||||
TS_reader_p ts_r;
|
||||
|
||||
// The temporary read buffer used by our ts reader.
|
||||
uint8_t *tmp_buf;
|
||||
uint32_t tmp_len;
|
||||
|
||||
// ts packet counter for error reporting.
|
||||
uint32_t ts_counter;
|
||||
|
||||
// packet counter.
|
||||
uint32_t pkt_counter;
|
||||
|
||||
// Last continuity counter.
|
||||
int last_cc;
|
||||
|
||||
// Do we think we currently have cc?
|
||||
int have_cc;
|
||||
|
||||
/*! In 90kHz units, what do you reckon you need to add to
|
||||
* PCR to make it into packet time?
|
||||
*/
|
||||
int64_t pcr_time_offset;
|
||||
|
||||
/*! What was the last difference between pcr_time_offset and
|
||||
* the measured time offset?
|
||||
*/
|
||||
int64_t last_time_offset;
|
||||
|
||||
/*! Do we think pcr_time_offset is valid at the minute? */
|
||||
int pcr_time_offset_valid;
|
||||
|
||||
/*! How far do we need to skew (in 90kHz units) to signal a discontinuity? */
|
||||
int64_t skew_discontinuity_threshold;
|
||||
|
||||
/*! Time of last discontinuity, in us */
|
||||
int64_t last_d_us;
|
||||
|
||||
} pcapreport_ctx_t;
|
||||
|
||||
// Discontinuity threshold is 6s.
|
||||
#define SKEW_DISCONTINUITY_THRESHOLD (6*90000)
|
||||
|
||||
static void print_usage();
|
||||
static int write_out_packet(pcapreport_ctx_t *pctx,
|
||||
const uint8_t *data,
|
||||
const uint32_t len);
|
||||
|
||||
static int digest_times(pcapreport_ctx_t *ctx,
|
||||
pcaprec_hdr_t *pcap_pkt_hdr,
|
||||
ethernet_packet_t *epkt,
|
||||
ipv4_header_t *ipv4_header,
|
||||
ipv4_udp_header_t *udp_header,
|
||||
const uint8_t *data,
|
||||
const uint32_t len);
|
||||
|
||||
static int digest_times_read(void *handle, char *out_buf, size_t len);
|
||||
static int digest_times_seek(void *handle, offset_t val);
|
||||
|
||||
|
||||
static void print_usage()
|
||||
{
|
||||
printf("Usage: pcapreport [switches] [<infile>] [switches]\n"
|
||||
|
@ -79,10 +140,18 @@ static void print_usage()
|
|||
" -d <dest ip>:<port> Select data with the given destination IP and port.\n"
|
||||
" --dump-data | -D Dump any data in the input file to stdout.\n"
|
||||
" --extra-dump | -e Dump only data which isn't being sent to the -o file.\n"
|
||||
" --times | -t Report on PCR vs PCAP timing for the destination specified in -d.\n"
|
||||
" --verbose | -v Output metadata about every packet.\n"
|
||||
" --skew-discontinuity-threshold <number>\n"
|
||||
" Gives the skew discontinuity threshold in 90kHz units.\n"
|
||||
"\n"
|
||||
" Specifying 0.0.0.0 for destination IP or 0 for destination port will capture all\n"
|
||||
" hosts and ports respectively.\n"
|
||||
"\n"
|
||||
" Network packet and TS packet numbers start at 0.\n"
|
||||
"\n"
|
||||
" Positive skew means that we recieved too low a PCR for this timestamp.\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -95,6 +164,8 @@ int main(int argc, char **argv)
|
|||
|
||||
memset(&ctx, '\0', sizeof(pcapreport_ctx_t));
|
||||
|
||||
ctx.skew_discontinuity_threshold = SKEW_DISCONTINUITY_THRESHOLD;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
print_usage();
|
||||
|
@ -124,6 +195,16 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
else if (!strcmp("-times", argv[ii]) ||
|
||||
!strcmp("--times", argv[ii]) || !strcmp("-t", argv[ii]))
|
||||
{
|
||||
++ctx.time_report;
|
||||
}
|
||||
else if (!strcmp("-verbose", argv[ii]) ||
|
||||
!strcmp("--verbose", argv[ii]) || !strcmp("-v", argv[ii]))
|
||||
{
|
||||
++ctx.verbose;
|
||||
}
|
||||
else if (!strcmp("--d", argv[ii]) || !strcmp("-d", argv[ii]))
|
||||
{
|
||||
char *hostname;
|
||||
|
@ -149,6 +230,18 @@ int main(int argc, char **argv)
|
|||
{
|
||||
++ctx.dump_extra;
|
||||
}
|
||||
else if (!strcmp("--skew-discontinuity-threshold", argv[ii]))
|
||||
{
|
||||
int val;
|
||||
int rv =
|
||||
int_value("pcapreport", argv[ii], argv[ii+1], TRUE, 0,
|
||||
&val);
|
||||
ctx.skew_discontinuity_threshold = val;
|
||||
if (rv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "### pcapreport: "
|
||||
|
@ -208,7 +301,6 @@ int main(int argc, char **argv)
|
|||
|
||||
{
|
||||
int done = 0;
|
||||
int pkt = 0;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
|
@ -228,9 +320,12 @@ int main(int argc, char **argv)
|
|||
{
|
||||
uint8_t *allocated = data;
|
||||
|
||||
printf("Packet: Time = %d.%d orig_len = %d \n",
|
||||
if (ctx.verbose)
|
||||
{
|
||||
printf("pkt: Time = %d.%d orig_len = %d \n",
|
||||
rec_hdr.ts_sec, rec_hdr.ts_usec,
|
||||
rec_hdr.orig_len);
|
||||
}
|
||||
|
||||
if (!(ctx.pcap_hdr.network == PCAP_NETWORK_TYPE_ETHERNET))
|
||||
{
|
||||
|
@ -255,7 +350,10 @@ int main(int argc, char **argv)
|
|||
goto dump_out;
|
||||
}
|
||||
|
||||
printf("Ethernet: src %02x:%02x:%02x:%02x:%02x:%02x "
|
||||
|
||||
if (ctx.verbose)
|
||||
{
|
||||
printf("++ 802.11: src %02x:%02x:%02x:%02x:%02x:%02x "
|
||||
" dst %02x:%02x:%02x:%02x:%02x:%02x "
|
||||
"typeorlen 0x%04x\n",
|
||||
epkt.src_addr[0], epkt.src_addr[1],
|
||||
|
@ -265,6 +363,7 @@ int main(int argc, char **argv)
|
|||
epkt.dst_addr[2], epkt.dst_addr[3],
|
||||
epkt.dst_addr[4], epkt.dst_addr[5],
|
||||
epkt.typeorlen);
|
||||
}
|
||||
|
||||
data = &data[out_st];
|
||||
len = out_len;
|
||||
|
@ -285,17 +384,19 @@ int main(int argc, char **argv)
|
|||
goto dump_out;
|
||||
}
|
||||
|
||||
printf("IPv4: src = %s",
|
||||
if (ctx.verbose)
|
||||
{
|
||||
printf("++ IPv4: src = %s",
|
||||
ipv4_addr_to_string(ipv4_hdr.src_addr));
|
||||
printf(" dest = %s \n",
|
||||
ipv4_addr_to_string(ipv4_hdr.dest_addr));
|
||||
|
||||
printf(
|
||||
"IPv4: version = 0x%x hdr_length = 0x%x"
|
||||
"++ IPv4: version = 0x%x hdr_length = 0x%x"
|
||||
" serv_type = 0x%08x length = 0x%04x\n"
|
||||
"IPv4: ident = 0x%04x flags = 0x%02x"
|
||||
"++ IPv4: ident = 0x%04x flags = 0x%02x"
|
||||
" frag_offset = 0x%04x ttl = %d\n"
|
||||
"IPv4: proto = %d csum = 0x%04x\n",
|
||||
"++ IPv4: proto = %d csum = 0x%04x\n",
|
||||
ipv4_hdr.version,
|
||||
ipv4_hdr.hdr_length,
|
||||
ipv4_hdr.serv_type,
|
||||
|
@ -306,6 +407,7 @@ int main(int argc, char **argv)
|
|||
ipv4_hdr.ttl,
|
||||
ipv4_hdr.proto,
|
||||
ipv4_hdr.csum);
|
||||
}
|
||||
|
||||
data = &data[out_st];
|
||||
len = out_len;
|
||||
|
@ -325,41 +427,41 @@ int main(int argc, char **argv)
|
|||
goto dump_out;
|
||||
}
|
||||
|
||||
printf("UDP: src port = %d "
|
||||
if (ctx.verbose)
|
||||
{
|
||||
printf("++ udp: src port = %d "
|
||||
"dest port = %d len = %d \n",
|
||||
udp_hdr.source_port,
|
||||
udp_hdr.dest_port,
|
||||
udp_hdr.length);
|
||||
}
|
||||
|
||||
data = &data[out_st];
|
||||
len = out_len;
|
||||
|
||||
if (ctx.output_name &&
|
||||
if (
|
||||
(!ctx.output_dest_addr || (ipv4_hdr.dest_addr == ctx.output_dest_addr)) &&
|
||||
(!ctx.output_dest_port || (udp_hdr.dest_port == ctx.output_dest_port)))
|
||||
{
|
||||
++sent_to_output;
|
||||
if (!ctx.output_file)
|
||||
|
||||
if (ctx.time_report)
|
||||
{
|
||||
ctx.output_file = fopen(ctx.output_name, "wb");
|
||||
if (!ctx.output_file)
|
||||
{
|
||||
fprintf(stderr,"### pcapreport: Cannot open %s .\n",
|
||||
ctx.output_name);
|
||||
return 1;
|
||||
rv =digest_times(&ctx,
|
||||
&rec_hdr,
|
||||
&epkt,
|
||||
&ipv4_hdr,
|
||||
&udp_hdr,
|
||||
data, len);
|
||||
if (rv) { return rv; }
|
||||
}
|
||||
if (ctx.output_name)
|
||||
{
|
||||
rv = write_out_packet(&ctx, data, len);
|
||||
if (rv) { return rv; }
|
||||
}
|
||||
|
||||
printf(">> Dumping %d bytes to output file.\n", len);
|
||||
rv = fwrite(data, len, 1, ctx.output_file);
|
||||
if (rv != 1)
|
||||
{
|
||||
fprintf(stderr, "### pcapreport: Couldn't write %d bytes"
|
||||
" to %s (error = %d).\n",
|
||||
len, ctx.output_name,
|
||||
ferror(ctx.output_file));
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,11 +478,12 @@ int main(int argc, char **argv)
|
|||
default:
|
||||
// Some other error.
|
||||
fprintf(stderr, "### pcapreport: Can't read packet %d - code %d\n",
|
||||
pkt, err);
|
||||
ctx.pkt_counter, err);
|
||||
++done;
|
||||
break;
|
||||
}
|
||||
++pkt;
|
||||
++ctx.pkt_counter;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,4 +496,235 @@ int main(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int digest_times(pcapreport_ctx_t *ctx,
|
||||
pcaprec_hdr_t *pcap_pkt_hdr,
|
||||
ethernet_packet_t *epkt,
|
||||
ipv4_header_t *ipv4_header,
|
||||
ipv4_udp_header_t *udp_header,
|
||||
const uint8_t *data,
|
||||
const uint32_t len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (!ctx->ts_r)
|
||||
{
|
||||
rv = build_TS_reader_with_fns(ctx,
|
||||
digest_times_read,
|
||||
digest_times_seek,
|
||||
&ctx->ts_r);
|
||||
if (rv)
|
||||
{
|
||||
fprintf(stderr, "### pcapreport: Cannot create ts reader.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add all our data to the pool.
|
||||
|
||||
ctx->tmp_buf = (uint8_t *)realloc(ctx->tmp_buf, ctx->tmp_len + len);
|
||||
memcpy(&ctx->tmp_buf[ctx->tmp_len], data, len);
|
||||
ctx->tmp_len += len;
|
||||
|
||||
// Now read out all the ts packets we can.
|
||||
while (1)
|
||||
{
|
||||
uint8_t *pkt;
|
||||
int rv;
|
||||
|
||||
rv = read_next_TS_packet(ctx->ts_r, &pkt);
|
||||
if (rv == EOF)
|
||||
{
|
||||
// Got to EOF - return for more data
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Right. Split it ..
|
||||
{
|
||||
uint32_t pid;
|
||||
int pusi;
|
||||
uint8_t *adapt;
|
||||
int adapt_len;
|
||||
uint8_t *payload;
|
||||
int payload_len;
|
||||
|
||||
rv = split_TS_packet(pkt, &pid, &pusi, &adapt, &adapt_len,
|
||||
&payload, &payload_len);
|
||||
if (rv)
|
||||
{
|
||||
printf(">> WARNING: TS packet %d [ packet %d @ %d.%d s ] cannot be split.\n",
|
||||
ctx->ts_counter, ctx->pkt_counter,
|
||||
pcap_pkt_hdr->ts_sec, pcap_pkt_hdr->ts_usec);
|
||||
}
|
||||
else
|
||||
{
|
||||
//int cc;
|
||||
|
||||
// PCR ?
|
||||
if (adapt && adapt_len)
|
||||
{
|
||||
int has_pcr;
|
||||
uint64_t pcr;
|
||||
uint64_t t_pcr;
|
||||
int64_t pcr_time_offset;
|
||||
|
||||
get_PCR_from_adaptation_field(adapt, adapt_len, &has_pcr,
|
||||
&pcr);
|
||||
if (has_pcr)
|
||||
{
|
||||
printf(">> Found PCR %lld at %d.%d s \n",
|
||||
pcr, pcap_pkt_hdr->ts_sec, pcap_pkt_hdr->ts_usec);
|
||||
|
||||
// PCR pops out in 27MHz units. Let's do all our comparisons
|
||||
// in 90kHz.
|
||||
pcr = pcr / 300;
|
||||
t_pcr = (((int64_t)pcap_pkt_hdr->ts_usec*9)/100) +
|
||||
((int64_t)pcap_pkt_hdr->ts_sec * 90000);
|
||||
|
||||
// printf("pcr = %lld t_pcr = %lld diff = %lld\n",
|
||||
// pcr, t_pcr,
|
||||
// t_pcr - pcr);
|
||||
|
||||
pcr_time_offset = ((int64_t)t_pcr - (int64_t)pcr);
|
||||
if (ctx->pcr_time_offset_valid)
|
||||
{
|
||||
int64_t skew = (pcr_time_offset - ctx->pcr_time_offset);
|
||||
|
||||
if (skew > ctx->skew_discontinuity_threshold ||
|
||||
skew < -ctx->skew_discontinuity_threshold)
|
||||
{
|
||||
printf(">> Skew discontinuity! Skew = %lld (> %lld) at"
|
||||
" ts = %d network = %d (PCR %lld Time %d.%d)\n",
|
||||
skew, ctx->skew_discontinuity_threshold,
|
||||
ctx->ts_counter, ctx->pkt_counter,
|
||||
pcr, pcap_pkt_hdr->ts_sec,
|
||||
pcap_pkt_hdr->ts_usec);
|
||||
|
||||
ctx->pcr_time_offset = pcr_time_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t rel_tim;
|
||||
double skew_rate;
|
||||
|
||||
rel_tim = ((int64_t)pcap_pkt_hdr->ts_usec) +
|
||||
((int64_t)pcap_pkt_hdr->ts_sec * 1000000);
|
||||
|
||||
rel_tim -= ctx->last_d_us;
|
||||
|
||||
skew_rate = (double)skew / ((double)((double)rel_tim / (60*1000000)));
|
||||
|
||||
printf(">> [ts %d net %d ] PCR %lld Time %d.%d [rel %d.%d] - skew = %lld (delta = %lld, rate = %.4g PTS/min)\n",
|
||||
ctx->ts_counter, ctx->pkt_counter,
|
||||
pcr,
|
||||
pcap_pkt_hdr->ts_sec, pcap_pkt_hdr->ts_usec,
|
||||
(int)(rel_tim / (int64_t)1000000),
|
||||
(int)rel_tim%1000000,
|
||||
skew, pcr_time_offset - ctx->last_time_offset,
|
||||
skew_rate);
|
||||
}
|
||||
ctx->last_time_offset = pcr_time_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->pcr_time_offset = ctx->last_time_offset =
|
||||
pcr_time_offset;
|
||||
ctx->last_d_us =
|
||||
((int64_t)pcap_pkt_hdr->ts_usec) +
|
||||
(((int64_t)pcap_pkt_hdr->ts_sec) * 1000000);
|
||||
|
||||
ctx->pcr_time_offset_valid = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// CC?
|
||||
cc = pkt[3]&0x0f;
|
||||
//printf("cc = %d \n", cc);
|
||||
if (!ctx->have_cc)
|
||||
{
|
||||
ctx->have_cc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cc != ((ctx->last_cc + 1)&0xf))
|
||||
{
|
||||
printf(">> CC discontinuity! ts = %d network = %d expected %d got %d.\n",
|
||||
ctx->ts_counter, ctx->pkt_counter,
|
||||
(ctx->last_cc+1)&0xf,
|
||||
cc);
|
||||
}
|
||||
}
|
||||
ctx->last_cc = cc;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
++ctx->ts_counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int digest_times_read(void *handle, char *out_buf, size_t len)
|
||||
{
|
||||
pcapreport_ctx_t *ctx = (pcapreport_ctx_t *)handle;
|
||||
int nr_bytes = (len < ctx->tmp_len ? len : ctx->tmp_len);
|
||||
int new_tmp_len = ctx->tmp_len - nr_bytes;
|
||||
|
||||
memcpy(out_buf, ctx->tmp_buf, nr_bytes);
|
||||
memmove(ctx->tmp_buf, &ctx->tmp_buf[nr_bytes],
|
||||
new_tmp_len);
|
||||
ctx->tmp_len = new_tmp_len;
|
||||
// printf(">> read %d bytes from intermediate buffer. \n", nr_bytes);
|
||||
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
static int digest_times_seek(void *handle, offset_t val)
|
||||
{
|
||||
// Cannot seek in a ts stream.
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int write_out_packet(pcapreport_ctx_t *ctx,
|
||||
const uint8_t *data,
|
||||
const uint32_t len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (ctx->output_name)
|
||||
{
|
||||
if (!ctx->output_file)
|
||||
{
|
||||
ctx->output_file = fopen(ctx->output_name, "wb");
|
||||
if (!ctx->output_file)
|
||||
{
|
||||
fprintf(stderr,"### pcapreport: Cannot open %s .\n",
|
||||
ctx->output_name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->verbose)
|
||||
{
|
||||
printf("++ Dumping %d bytes to output file.\n", len);
|
||||
}
|
||||
rv = fwrite(data, len, 1, ctx->output_file);
|
||||
if (rv != 1)
|
||||
{
|
||||
fprintf(stderr, "### pcapreport: Couldn't write %d bytes"
|
||||
" to %s (error = %d).\n",
|
||||
len, ctx->output_name,
|
||||
ferror(ctx->output_file));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* End file */
|
||||
|
|
54
ts.c
54
ts.c
|
@ -1202,6 +1202,8 @@ extern int build_TS_reader(int file,
|
|||
return 1;
|
||||
}
|
||||
|
||||
memset(new, '\0', SIZEOF_TS_READER);
|
||||
|
||||
new->file = file;
|
||||
new->posn = 0;
|
||||
new->read_ahead_ptr = NULL;
|
||||
|
@ -1210,6 +1212,39 @@ extern int build_TS_reader(int file,
|
|||
*tsreader = new;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Build a TS packet reader using the given functions as
|
||||
* read() and seek().
|
||||
*
|
||||
* Returns 0 on success, 1 on failure.
|
||||
*/
|
||||
extern int build_TS_reader_with_fns(void *handle,
|
||||
int (*read_fn)(void *, char *, size_t),
|
||||
int (*seek_fn)(void *, offset_t),
|
||||
TS_reader_p *tsreader)
|
||||
{
|
||||
TS_reader_p new = malloc(SIZEOF_TS_READER);
|
||||
if (new == NULL)
|
||||
{
|
||||
fprintf(stderr,"### Unable to allocate TS read-ahead buffer\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(new, '\0', SIZEOF_TS_READER);
|
||||
|
||||
new->file = -1;
|
||||
new->handle = handle;
|
||||
new->read_fn = read_fn;
|
||||
new->seek_fn = seek_fn;
|
||||
new->posn = 0;
|
||||
new->read_ahead_ptr = NULL;
|
||||
new->read_ahead_end = NULL;
|
||||
|
||||
*tsreader = new;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open a file to read TS packets from.
|
||||
|
@ -1297,9 +1332,17 @@ extern int seek_using_TS_reader(TS_reader_p tsreader,
|
|||
tsreader->read_ahead_ptr = NULL;
|
||||
tsreader->read_ahead_end = NULL;
|
||||
tsreader->posn = posn;
|
||||
|
||||
if (tsreader->seek_fn)
|
||||
{
|
||||
return tsreader->seek_fn(tsreader->handle, posn);
|
||||
}
|
||||
else
|
||||
{
|
||||
return seek_file(tsreader->file,posn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the next several TS packets, possibly not from the start
|
||||
*
|
||||
|
@ -1333,10 +1376,19 @@ static int read_next_TS_packets(TS_reader_p tsreader,
|
|||
{
|
||||
// Try to allow for partial reads
|
||||
while (total < TS_READ_AHEAD_BYTES)
|
||||
{
|
||||
if (tsreader->read_fn)
|
||||
{
|
||||
length = tsreader->read_fn(tsreader->handle,
|
||||
&(tsreader->read_ahead[total]),
|
||||
TS_READ_AHEAD_BYTES-total);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = read(tsreader->file,
|
||||
&(tsreader->read_ahead[total]),
|
||||
TS_READ_AHEAD_BYTES - total);
|
||||
}
|
||||
if (length == 0) // EOF - no more data to read
|
||||
break;
|
||||
else if (length == -1)
|
||||
|
|
|
@ -52,6 +52,14 @@ struct _ts_reader
|
|||
{
|
||||
int file; // the file to read from
|
||||
offset_t posn; // the position of the next-to-be-read TS packet
|
||||
void *handle; // handle to pass to read_fn and seek_fn.
|
||||
|
||||
|
||||
/* Reader and seek functions. If these are non-NULL we call them
|
||||
* when we would call read().
|
||||
*/
|
||||
int (*read_fn)(void *, char *, size_t);
|
||||
int (*seek_fn)(void *, offset_t);
|
||||
|
||||
byte read_ahead[TS_READ_AHEAD_COUNT*TS_PACKET_SIZE];
|
||||
byte *read_ahead_ptr; // location of next packet in said array
|
||||
|
|
10
ts_fns.h
10
ts_fns.h
|
@ -289,6 +289,16 @@ extern int write_TS_null_packet(TS_writer_p output);
|
|||
*/
|
||||
extern int build_TS_reader(int file,
|
||||
TS_reader_p *tsreader);
|
||||
|
||||
|
||||
/* Build a TS packet reader using given functions to read and
|
||||
* seek.
|
||||
*/
|
||||
extern int build_TS_reader_with_fns(void *handle,
|
||||
int (*read_fn)(void *, char *, size_t),
|
||||
int (*seek_fn)(void *, offset_t),
|
||||
TS_reader_p *tsreader);
|
||||
|
||||
/*
|
||||
* Open a file to read TS packets from.
|
||||
*
|
||||
|
|
Ładowanie…
Reference in New Issue