[FFmpeg-devel] [PATCH] aviobuf: Retry if the read/write function returns AVERROR(EAGAIN)
Martin Storsjö
martin
Mon Jan 3 16:26:03 CET 2011
On Mon, 3 Jan 2011, Reimar D?ffinger wrote:
> On 3 jan 2011, at 13:27, Martin Storsjo <martin at martin.st> wrote:
> > ---
> > libavformat/aviobuf.c | 28 +++++++++++++++++++++++++---
> > 1 files changed, 25 insertions(+), 3 deletions(-)
> >
> > diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
> > index df76507..5aff31c 100644
> > --- a/libavformat/aviobuf.c
> > +++ b/libavformat/aviobuf.c
> > @@ -19,6 +19,9 @@
> > * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> > */
> >
> > +/* needed for usleep() */
> > +#define _XOPEN_SOURCE 600
> > +#include <unistd.h>
> > #include "libavutil/crc.h"
> > #include "libavutil/intreadwrite.h"
> > #include "avformat.h"
> > @@ -88,11 +91,29 @@ ByteIOContext *av_alloc_put_byte(
> > return s;
> > }
> >
> > +static inline int retry_transfer_wrapper(void *opaque, unsigned char *buf,
> > + int size,
> > + int (*transfer_func)(void *, unsigned char *, int)) {
> > + int fast_retries = 5;
> > + while (1) {
> > + int ret = transfer_func(opaque, buf, size);
> > + if (ret == AVERROR(EAGAIN)) {
> > + if (fast_retries)
> > + fast_retries--;
> > + else
> > + usleep(1000);
> > + } else
> > + return ret;
> > + }
> > +}
> > +
> > static void flush_buffer(ByteIOContext *s)
> > {
> > if (s->buf_ptr > s->buffer) {
> > if (s->write_packet && !s->error){
> > - int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
> > + int ret= retry_transfer_wrapper(s->opaque, s->buffer,
> > + s->buf_ptr - s->buffer,
> > + s->write_packet);
>
> This duplicates code, also the question is why the read_packet and
> write_packet functions should be allowed to return EAGAIN and if this is
> sufficiently documented.
It duplicates a little of the logic from avio.c:retry_transfer_wrapper,
yes, but this version is a bit simpler, since the re-reading for short
reads already exist in aviobuf.
If we'd want to avoid this duplication, a third function (e.g.
url_read_retry) could be added which would retry on EAGAIN but return as
soon as some data is available. Or sharing the code from avio.c in some
other way... (Just setting url_read_complete as packet_read in url_fdopen,
instead of url_read, wouldn't work properly, since fill_buffer() then
would block needlessly long, filling the whole buffer even if only a
single byte was needed.) But that would only work for the url_fdopen()
case, not for other functions wrapped in ByteIOContext.
As for whether they are allowed to return EAGAIN - url_read_complete
already handles EAGAIN, so url_read seems to be allowed to return it,
which ByteIOContext uses directly at the moment. Not sure if write_packet
is allowed to return it though - url_write hides it at least.
// Martin
More information about the ffmpeg-devel
mailing list