On Sat, 19 Jul 2014 19:21:47 -0400 siret...@gmail.com wrote: > From: John Peterson <john.peters...@hotmail.com> > > Useful to simulate low performance input. > The minimum resolution is 1 Kib/s. > > The input stream packet size setting can be used to test the performance > with different packet sizes at the maximum or simulated maximum input > rate. > --- > libavformat/avio.h | 15 ++++++++++++ > libavformat/aviobuf.c | 63 > +++++++++++++++++++++++++++++++++++++++++++++++++++ > libavformat/utils.c | 5 +++- > 3 files changed, 82 insertions(+), 1 deletion(-) > > diff --git a/libavformat/avio.h b/libavformat/avio.h > index 3360e82..b16fd00 100644 > --- a/libavformat/avio.h > +++ b/libavformat/avio.h > @@ -54,6 +54,19 @@ typedef struct AVIOInterruptCB { > } AVIOInterruptCB; > > /** > + * Input stream throttle queue. > + */ > +typedef struct traffic { > + int64_t time; > + int traf; > +} traffic; > +typedef struct traffic_queue { > + int size; > + int len; > + traffic *data; > +} traffic_queue; > + > +/** > * Bytestream IO Context. > * New fields can be added to the end with minor version bumps. > * Removal, reordering and changes to existing fields require a major > @@ -96,6 +109,8 @@ typedef struct AVIOContext { > int eof_reached; /**< true if eof reached */ > int write_flag; /**< true if open for writing */ > int max_packet_size; > + int throttle; /**< command line argument throttle */ > + traffic_queue t_queue; /**< traffic queue for throttle */ > unsigned long checksum; > unsigned char *checksum_ptr; > unsigned long (*update_checksum)(unsigned long checksum, const uint8_t > *buf, unsigned int size); > diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c > index cc79146..f957625 100644 > --- a/libavformat/aviobuf.c > +++ b/libavformat/aviobuf.c > @@ -30,8 +30,10 @@ > #include "internal.h" > #include "url.h" > #include <stdarg.h> > +#include <unistd.h> > > #define IO_BUFFER_SIZE 32768 > +#define INPUT_HISTORY_SIZE 10 // s > > /** > * Do seeks within this distance ahead of the current buffer by skipping > @@ -51,7 +53,11 @@ static const AVClass *ffio_url_child_class_next(const > AVClass *prev) > return prev ? NULL : &ffurl_context_class; > } > > +#define OFFSET(x) offsetof(AVIOContext, x) > +#define D AV_OPT_FLAG_DECODING_PARAM > static const AVOption ffio_url_options[] = { > + { "in_packet_size", "set max input packet size", > OFFSET(max_packet_size), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, D }, > + { "throttle", "set max input rate in Kib/s", OFFSET(throttle), > AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, D }, > { NULL }, > }; > > @@ -359,6 +365,57 @@ void avio_wb24(AVIOContext *s, unsigned int val) > > /* Input stream */ > > +/* traffic history for input throttle */ > +static void t_queue_push(traffic_queue *queue, int64_t time, int traf) > +{ > + traffic* data; > + queue->len++; > + data = av_realloc(queue->data, sizeof(traffic)*queue->len); > + if (!data) > + return; > + queue->data = data; > + queue->data[queue->len-1].time = time; > + queue->data[queue->len-1].traf = traf; > +} > + > +static void t_queue_pop(traffic_queue *queue) > +{ > + int i; > + for (i = 0; i < queue->len; i++) { > + if (queue->data[i].time < av_gettime()-INPUT_HISTORY_SIZE*1000000) { > + memmove(queue->data + i, queue->data + i + 1, > sizeof(traffic)*(queue->len - i - 1)); > + queue->len--; > + } > + } > +} > + > +/* input throttle */ > +static int64_t avio_throttle_rate(traffic_queue *queue, int64_t time) > +{ > + int64_t sum = 0; > + int i; > + for (i = 0; i < queue->len; i++) { > + if (queue->data[i].time > av_gettime()-time) > + sum += queue->data[i].traf; > + } > + return (double)sum/((double)time/1000000.0); // B/s > +} > + > +static int avio_throttle(AVIOContext *s) > +{ > + if (!s->throttle) return 0; > + t_queue_pop(&s->t_queue); > + // measure speed at multiple intervals to create an even transfer rate > + if (avio_throttle_rate(&s->t_queue, 0.001*1000000) > s->throttle*0x80 > + || avio_throttle_rate(&s->t_queue, 0.01*1000000) > s->throttle*0x80 > + || avio_throttle_rate(&s->t_queue, 0.1*1000000) > s->throttle*0x80 > + || avio_throttle_rate(&s->t_queue, 1*1000000) > s->throttle*0x80 > + || avio_throttle_rate(&s->t_queue, 10*1000000) > s->throttle*0x80 > + ) > + return 1; > + return 0; > +} > + > static void fill_buffer(AVIOContext *s) > { > uint8_t *dst = !s->max_packet_size && > @@ -405,6 +462,12 @@ static void fill_buffer(AVIOContext *s) > s->pos += len; > s->buf_ptr = dst; > s->buf_end = dst + len; > + > + // throttle > + t_queue_push(&s->t_queue, av_gettime(), len); > + while (s->throttle && avio_throttle(s)) { > + usleep(0.1*1000000); > + } > } > } > > diff --git a/libavformat/utils.c b/libavformat/utils.c > index 7a054af..2211b9c 100644 > --- a/libavformat/utils.c > +++ b/libavformat/utils.c > @@ -427,8 +427,11 @@ int avformat_open_input(AVFormatContext **ps, const char > *filename, > } > > /* e.g. AVFMT_NOFILE formats will not have a AVIOContext */ > - if (s->pb) > + if (s->pb) { > ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); > + if ((ret = av_opt_set_dict(s->pb, &tmp)) < 0) > + goto fail; > + } > > if (s->iformat->read_header) > if ((ret = s->iformat->read_header(s)) < 0)
I'd say no. Useful for debugging sometimes (or is there a real usecase???), but does it really have to be in the main repo? Also, this should be implemented as nested protocol, not somehow hacking it into aviobuf.c. _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel