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

Reply via email to