On 20/07/14 13:55, wm4 wrote: > 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.
As protocol would be surely _much_ easier to use IMHO. lu _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel