From f5a478f65d7262dbe194641d384f24fbbc03ed85 Mon Sep 17 00:00:00 2001 From: Roman Shaposhnik Date: Thu, 21 Sep 2006 07:31:53 +0000 Subject: [PATCH] * Moving FifoBuffer out of libavformat/avformat.h and libavformat/utils.c into libavutil Originally committed as revision 6310 to svn://svn.ffmpeg.org/ffmpeg/trunk --- ffmpeg.c | 26 +++++---- libavformat/avformat.h | 23 -------- libavformat/dvenc.c | 21 ++++---- libavformat/gxfenc.c | 15 +++--- libavformat/mpeg.c | 43 +++++++-------- libavformat/utils.c | 140 ------------------------------------------------- libavutil/Makefile | 3 +- libavutil/fifo.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++ libavutil/fifo.h | 25 +++++++++ 9 files changed, 212 insertions(+), 219 deletions(-) create mode 100644 libavutil/fifo.c create mode 100644 libavutil/fifo.h diff --git a/ffmpeg.c b/ffmpeg.c index cf60ed4..76a41cd 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -23,6 +23,7 @@ #include "framehook.h" #include "dsputil.h" #include "opt.h" +#include "fifo.h" #ifndef __MINGW32__ #include @@ -267,7 +268,7 @@ typedef struct AVOutputStream { /* audio only */ int audio_resample; ReSampleContext *resample; /* for audio resampling */ - FifoBuffer fifo; /* for compression: one audio fifo per codec */ + AVFifoBuffer fifo; /* for compression: one audio fifo per codec */ FILE *logfile; } AVOutputStream; @@ -471,7 +472,7 @@ static void do_audio_out(AVFormatContext *s, if(audio_sync_method){ double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts - - fifo_size(&ost->fifo, ost->fifo.rptr)/(ost->st->codec->channels * 2); + - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); double idelta= delta*ist->st->codec->sample_rate / enc->sample_rate; int byte_delta= ((int)idelta)*2*ist->st->codec->channels; @@ -508,13 +509,13 @@ static void do_audio_out(AVFormatContext *s, assert(ost->audio_resample); if(verbose > 2) fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate); -// fprintf(stderr, "drift:%f len:%d opts:%lld ipts:%lld fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), fifo_size(&ost->fifo, ost->fifo.rptr)/(ost->st->codec->channels * 2)); +// fprintf(stderr, "drift:%f len:%d opts:%lld ipts:%lld fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2)); av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate); } } }else ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate) - - fifo_size(&ost->fifo, ost->fifo.rptr)/(ost->st->codec->channels * 2); //FIXME wrong + - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong if (ost->audio_resample) { buftmp = audio_buf; @@ -530,13 +531,11 @@ static void do_audio_out(AVFormatContext *s, /* now encode as many frames as possible */ if (enc->frame_size > 1) { /* output resampled raw samples */ - fifo_write(&ost->fifo, buftmp, size_out, - &ost->fifo.wptr); + av_fifo_write(&ost->fifo, buftmp, size_out); frame_bytes = enc->frame_size * 2 * enc->channels; - while (fifo_read(&ost->fifo, audio_buf, frame_bytes, - &ost->fifo.rptr) == 0) { + while (av_fifo_read(&ost->fifo, audio_buf, frame_bytes) == 0) { AVPacket pkt; av_init_packet(&pkt); @@ -1317,14 +1316,13 @@ static int output_packet(AVInputStream *ist, int ist_index, switch(ost->st->codec->codec_type) { case CODEC_TYPE_AUDIO: - fifo_bytes = fifo_size(&ost->fifo, NULL); + fifo_bytes = av_fifo_size(&ost->fifo); ret = 0; /* encode any samples remaining in fifo */ if(fifo_bytes > 0 && enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { int fs_tmp = enc->frame_size; enc->frame_size = fifo_bytes / (2 * enc->channels); - if(fifo_read(&ost->fifo, (uint8_t *)samples, fifo_bytes, - &ost->fifo.rptr) == 0) { + if(av_fifo_read(&ost->fifo, (uint8_t *)samples, fifo_bytes) == 0) { ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, samples); } enc->frame_size = fs_tmp; @@ -1563,7 +1561,7 @@ static int av_encode(AVFormatContext **output_files, } else { switch(codec->codec_type) { case CODEC_TYPE_AUDIO: - if (fifo_init(&ost->fifo, 2 * MAX_AUDIO_PACKET_SIZE)) + if (av_fifo_init(&ost->fifo, 2 * MAX_AUDIO_PACKET_SIZE)) goto fail; if (codec->channels == icodec->channels && @@ -2018,8 +2016,8 @@ static int av_encode(AVFormatContext **output_files, fclose(ost->logfile); ost->logfile = NULL; } - fifo_free(&ost->fifo); /* works even if fifo is not - initialized but set to zero */ + av_fifo_free(&ost->fifo); /* works even if fifo is not + initialized but set to zero */ av_free(ost->pict_tmp.data[0]); if (ost->video_resample) sws_freeContext(ost->img_resample_ctx); diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 90c4f49..102dc92 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -441,29 +441,6 @@ void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload); void av_register_all(void); -typedef struct FifoBuffer { - uint8_t *buffer; - uint8_t *rptr, *wptr, *end; -} FifoBuffer; - -int fifo_init(FifoBuffer *f, int size); -void fifo_free(FifoBuffer *f); -int fifo_size(FifoBuffer *f, uint8_t *rptr); -int fifo_read(FifoBuffer *f, uint8_t *buf, int buf_size, uint8_t **rptr_ptr); -void fifo_write(FifoBuffer *f, const uint8_t *buf, int size, uint8_t **wptr_ptr); -int put_fifo(ByteIOContext *pb, FifoBuffer *f, int buf_size, uint8_t **rptr_ptr); -void fifo_realloc(FifoBuffer *f, unsigned int size); -static inline uint8_t fifo_peek(FifoBuffer *f, int offs) -{ - return f->buffer[(f->rptr - f->buffer + offs) % (f->end - f->buffer)]; -} -static inline void fifo_drain(FifoBuffer *f, int size) -{ - f->rptr += size; - if (f->rptr >= f->end) - f->rptr = f->buffer + (f->rptr - f->end); -} - /* media file input */ AVInputFormat *av_find_input_format(const char *short_name); AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened); diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index 17024fb..fd4025c 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -29,12 +29,13 @@ #include "avformat.h" #include "dvdata.h" #include "dv.h" +#include "fifo.h" struct DVMuxContext { const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ int n_ast; /* Number of stereo audio streams (up to 2) */ AVStream *ast[2]; /* Stereo audio streams */ - FifoBuffer audio_data[2]; /* Fifo for storing excessive amounts of PCM */ + AVFifoBuffer audio_data[2]; /* Fifo for storing excessive amounts of PCM */ int frames; /* Number of a current frame */ time_t start_time; /* Start time of recording */ int has_audio; /* frame under contruction has audio */ @@ -185,8 +186,8 @@ static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr) if (of*2 >= size) continue; - frame_ptr[d] = fifo_peek(&c->audio_data[channel], of*2+1); // FIXME: may be we have to admit - frame_ptr[d+1] = fifo_peek(&c->audio_data[channel], of*2); // that DV is a big endian PCM + frame_ptr[d] = av_fifo_peek(&c->audio_data[channel], of*2+1); // FIXME: may be we have to admit + frame_ptr[d+1] = av_fifo_peek(&c->audio_data[channel], of*2); // that DV is a big endian PCM } frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ } @@ -247,12 +248,12 @@ int dv_assemble_frame(DVMuxContext *c, AVStream* st, for (i = 0; i < c->n_ast && st != c->ast[i]; i++); /* FIXME: we have to have more sensible approach than this one */ - if (fifo_size(&c->audio_data[i], c->audio_data[i].rptr) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) + if (av_fifo_size(&c->audio_data[i]) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); - fifo_write(&c->audio_data[i], data, data_size, &c->audio_data[i].wptr); + av_fifo_write(&c->audio_data[i], data, data_size); /* Lets see if we've got enough audio for one DV frame */ - c->has_audio |= ((reqasize <= fifo_size(&c->audio_data[i], c->audio_data[i].rptr)) << i); + c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i); break; default: @@ -264,7 +265,7 @@ int dv_assemble_frame(DVMuxContext *c, AVStream* st, dv_inject_metadata(c, *frame); for (i=0; in_ast; i++) { dv_inject_audio(c, i, *frame); - fifo_drain(&c->audio_data[i], reqasize); + av_fifo_drain(&c->audio_data[i], reqasize); } c->has_video = 0; @@ -333,10 +334,10 @@ DVMuxContext* dv_init_mux(AVFormatContext* s) c->start_time = (time_t)s->timestamp; for (i=0; in_ast; i++) { - if (c->ast[i] && fifo_init(&c->audio_data[i], 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) < 0) { + if (c->ast[i] && av_fifo_init(&c->audio_data[i], 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) < 0) { while (i>0) { i--; - fifo_free(&c->audio_data[i]); + av_fifo_free(&c->audio_data[i]); } goto bail_out; } @@ -353,7 +354,7 @@ void dv_delete_mux(DVMuxContext *c) { int i; for (i=0; i < c->n_ast; i++) - fifo_free(&c->audio_data[i]); + av_fifo_free(&c->audio_data[i]); } #ifdef CONFIG_MUXERS diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 234e0a5..6fa7e96 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -20,12 +20,13 @@ #include "avformat.h" #include "gxf.h" #include "riff.h" +#include "fifo.h" #define GXF_AUDIO_PACKET_SIZE 65536 typedef struct GXFStreamContext { AVCodecContext *codec; - FifoBuffer audio_buffer; + AVFifoBuffer audio_buffer; uint32_t track_type; uint32_t sample_size; uint32_t sample_rate; @@ -604,7 +605,7 @@ static int gxf_write_header(AVFormatContext *s) sc->fields = -2; gxf->audio_tracks++; gxf->flags |= 0x04000000; /* audio is 16 bit pcm */ - fifo_init(&sc->audio_buffer, 3*GXF_AUDIO_PACKET_SIZE); + av_fifo_init(&sc->audio_buffer, 3*GXF_AUDIO_PACKET_SIZE); } else if (sc->codec->codec_type == CODEC_TYPE_VIDEO) { /* FIXME check from time_base ? */ if (sc->codec->height == 480 || sc->codec->height == 512) { /* NTSC or NTSC+VBI */ @@ -670,7 +671,7 @@ static int gxf_write_trailer(AVFormatContext *s) for (i = 0; i < s->nb_streams; ++i) { if (s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) { - fifo_free(&gxf->streams[i].audio_buffer); + av_fifo_free(&gxf->streams[i].audio_buffer); } if (s->streams[i]->codec->frame_number > gxf->nb_frames) gxf->nb_frames = 2 * s->streams[i]->codec->frame_number; @@ -762,12 +763,12 @@ static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt) static int gxf_new_audio_packet(GXFContext *gxf, GXFStreamContext *sc, AVPacket *pkt, int flush) { - int size = flush ? fifo_size(&sc->audio_buffer, NULL) : GXF_AUDIO_PACKET_SIZE; + int size = flush ? av_fifo_size(&sc->audio_buffer) : GXF_AUDIO_PACKET_SIZE; if (!size) return 0; av_new_packet(pkt, size); - fifo_read(&sc->audio_buffer, pkt->data, size, NULL); + av_fifo_read(&sc->audio_buffer, pkt->data, size); pkt->stream_index = sc->index; pkt->dts = sc->current_dts; sc->current_dts += size / 2; /* we only support 16 bit pcm mono for now */ @@ -784,10 +785,10 @@ static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pk if (s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) { GXFStreamContext *sc = &gxf->streams[i]; if (pkt && pkt->stream_index == i) { - fifo_write(&sc->audio_buffer, pkt->data, pkt->size, NULL); + av_fifo_write(&sc->audio_buffer, pkt->data, pkt->size); pkt = NULL; } - if (flush || fifo_size(&sc->audio_buffer, NULL) >= GXF_AUDIO_PACKET_SIZE) { + if (flush || av_fifo_size(&sc->audio_buffer) >= GXF_AUDIO_PACKET_SIZE) { if (gxf_new_audio_packet(gxf, sc, &new_pkt, flush) > 0) { pkt = &new_pkt; break; /* add pkt right now into list */ diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index 8846a59..7b965ba 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -18,6 +18,7 @@ */ #include "avformat.h" #include "bitstream.h" +#include "fifo.h" #define MAX_PAYLOAD_SIZE 4096 //#define DEBUG_SEEK @@ -35,7 +36,7 @@ typedef struct PacketDesc { } PacketDesc; typedef struct { - FifoBuffer fifo; + AVFifoBuffer fifo; uint8_t id; int max_buffer_size; /* in bytes */ int buffer_index; @@ -45,7 +46,7 @@ typedef struct { int packet_number; uint8_t lpcm_header[3]; int lpcm_align; - uint8_t *fifo_iframe_ptr; + int bytes_to_iframe; int align_iframe; int64_t vobu_start_pts; } StreamInfo; @@ -412,7 +413,7 @@ static int mpeg_mux_init(AVFormatContext *ctx) default: return -1; } - fifo_init(&stream->fifo, 16); + av_fifo_init(&stream->fifo, 16); } bitrate = 0; audio_bitrate = 0; @@ -708,14 +709,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, } } else if (s->is_dvd) { if (stream->align_iframe || s->packet_number == 0){ - int bytes_to_iframe; - int PES_bytes_to_fill; - if (stream->fifo_iframe_ptr >= stream->fifo.rptr) { - bytes_to_iframe = stream->fifo_iframe_ptr - stream->fifo.rptr; - } else { - bytes_to_iframe = (stream->fifo.end - stream->fifo.rptr) + (stream->fifo_iframe_ptr - stream->fifo.buffer); - } - PES_bytes_to_fill = s->packet_size - size - 10; + int PES_bytes_to_fill = s->packet_size - size - 10; if (pts != AV_NOPTS_VALUE) { if (dts != pts) @@ -724,7 +718,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, PES_bytes_to_fill -= 5; } - if (bytes_to_iframe == 0 || s->packet_number == 0) { + if (stream->bytes_to_iframe == 0 || s->packet_number == 0) { size = put_system_header(ctx, buf_ptr, 0); buf_ptr += size; size = buf_ptr - buffer; @@ -751,8 +745,8 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, s->last_scr= scr; buf_ptr += size; /* GOP Start */ - } else if (bytes_to_iframe < PES_bytes_to_fill) { - pad_packet_bytes = PES_bytes_to_fill - bytes_to_iframe; + } else if (stream->bytes_to_iframe < PES_bytes_to_fill) { + pad_packet_bytes = PES_bytes_to_fill - stream->bytes_to_iframe; } } } else { @@ -824,7 +818,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, startcode = 0x100 + id; } - stuffing_size = payload_size - fifo_size(&stream->fifo, stream->fifo.rptr); + stuffing_size = payload_size - av_fifo_size(&stream->fifo); // first byte doesnt fit -> reset pts/dts + stuffing if(payload_size <= trailer_size && pts != AV_NOPTS_VALUE){ @@ -951,8 +945,9 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, } /* output data */ - if(put_fifo(&ctx->pb, &stream->fifo, payload_size - stuffing_size, &stream->fifo.rptr) < 0) + if(av_fifo_generic_read(&stream->fifo, payload_size - stuffing_size, &put_buffer, &ctx->pb) < 0) return -1; + stream->bytes_to_iframe -= payload_size - stuffing_size; }else{ payload_size= stuffing_size= 0; @@ -1065,7 +1060,7 @@ retry: for(i=0; inb_streams; i++){ AVStream *st = ctx->streams[i]; StreamInfo *stream = st->priv_data; - const int avail_data= fifo_size(&stream->fifo, stream->fifo.rptr); + const int avail_data= av_fifo_size(&stream->fifo); const int space= stream->max_buffer_size - stream->buffer_index; int rel_space= 1024*space / stream->max_buffer_size; PacketDesc *next_pkt= stream->premux_packet; @@ -1125,7 +1120,7 @@ retry: st = ctx->streams[best_i]; stream = st->priv_data; - assert(fifo_size(&stream->fifo, stream->fifo.rptr) > 0); + assert(av_fifo_size(&stream->fifo) > 0); assert(avail_space >= s->packet_size || ignore_constraints); @@ -1141,7 +1136,7 @@ retry: //av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f scr:%f stream:%d\n", timestamp_packet->dts/90000.0, timestamp_packet->pts/90000.0, scr/90000.0, best_i); es_size= flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, scr, trailer_size); }else{ - assert(fifo_size(&stream->fifo, stream->fifo.rptr) == trailer_size); + assert(av_fifo_size(&stream->fifo) == trailer_size); es_size= flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, scr, trailer_size); } @@ -1204,11 +1199,11 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) stream->predecode_packet= pkt_desc; stream->next_packet= &pkt_desc->next; - fifo_realloc(&stream->fifo, fifo_size(&stream->fifo, NULL) + size + 1); + av_fifo_realloc(&stream->fifo, av_fifo_size(&stream->fifo) + size + 1); if (s->is_dvd){ if (is_iframe && (s->packet_number == 0 || (pts - stream->vobu_start_pts >= 36000))) { // min VOBU length 0.4 seconds (mpucoder) - stream->fifo_iframe_ptr = stream->fifo.wptr; + stream->bytes_to_iframe = av_fifo_size(&stream->fifo); stream->align_iframe = 1; stream->vobu_start_pts = pts; } else { @@ -1216,7 +1211,7 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) } } - fifo_write(&stream->fifo, buf, size, &stream->fifo.wptr); + av_fifo_write(&stream->fifo, buf, size); for(;;){ int ret= output_packet(ctx, 0); @@ -1248,8 +1243,8 @@ static int mpeg_mux_end(AVFormatContext *ctx) for(i=0;inb_streams;i++) { stream = ctx->streams[i]->priv_data; - assert(fifo_size(&stream->fifo, stream->fifo.rptr) == 0); - fifo_free(&stream->fifo); + assert(av_fifo_size(&stream->fifo) == 0); + av_fifo_free(&stream->fifo); } return 0; } diff --git a/libavformat/utils.c b/libavformat/utils.c index 77bc84a..425db9a 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -263,146 +263,6 @@ int av_dup_packet(AVPacket *pkt) return 0; } -/* fifo handling */ - -int fifo_init(FifoBuffer *f, int size) -{ - f->buffer = av_malloc(size); - if (!f->buffer) - return -1; - f->end = f->buffer + size; - f->wptr = f->rptr = f->buffer; - return 0; -} - -void fifo_free(FifoBuffer *f) -{ - av_free(f->buffer); -} - -int fifo_size(FifoBuffer *f, uint8_t *rptr) -{ - int size; - - if(!rptr) - rptr= f->rptr; - - if (f->wptr >= rptr) { - size = f->wptr - rptr; - } else { - size = (f->end - rptr) + (f->wptr - f->buffer); - } - return size; -} - -/** - * Get data from the fifo (returns -1 if not enough data). - */ -int fifo_read(FifoBuffer *f, uint8_t *buf, int buf_size, uint8_t **rptr_ptr) -{ - uint8_t *rptr; - int size, len; - - if(!rptr_ptr) - rptr_ptr= &f->rptr; - rptr = *rptr_ptr; - - if (f->wptr >= rptr) { - size = f->wptr - rptr; - } else { - size = (f->end - rptr) + (f->wptr - f->buffer); - } - - if (size < buf_size) - return -1; - while (buf_size > 0) { - len = f->end - rptr; - if (len > buf_size) - len = buf_size; - memcpy(buf, rptr, len); - buf += len; - rptr += len; - if (rptr >= f->end) - rptr = f->buffer; - buf_size -= len; - } - *rptr_ptr = rptr; - return 0; -} - -/** - * Resizes a FIFO. - */ -void fifo_realloc(FifoBuffer *f, unsigned int new_size){ - unsigned int old_size= f->end - f->buffer; - - if(old_size < new_size){ - uint8_t *old= f->buffer; - - f->buffer= av_realloc(f->buffer, new_size); - - f->rptr += f->buffer - old; - f->wptr += f->buffer - old; - - if(f->wptr < f->rptr){ - memmove(f->rptr + new_size - old_size, f->rptr, f->buffer + old_size - f->rptr); - f->rptr += new_size - old_size; - } - f->end= f->buffer + new_size; - } -} - -void fifo_write(FifoBuffer *f, const uint8_t *buf, int size, uint8_t **wptr_ptr) -{ - int len; - uint8_t *wptr; - - if(!wptr_ptr) - wptr_ptr= &f->wptr; - wptr = *wptr_ptr; - - while (size > 0) { - len = f->end - wptr; - if (len > size) - len = size; - memcpy(wptr, buf, len); - wptr += len; - if (wptr >= f->end) - wptr = f->buffer; - buf += len; - size -= len; - } - *wptr_ptr = wptr; -} - -/* get data from the fifo (return -1 if not enough data) */ -int put_fifo(ByteIOContext *pb, FifoBuffer *f, int buf_size, uint8_t **rptr_ptr) -{ - uint8_t *rptr = *rptr_ptr; - int size, len; - - if (f->wptr >= rptr) { - size = f->wptr - rptr; - } else { - size = (f->end - rptr) + (f->wptr - f->buffer); - } - - if (size < buf_size) - return -1; - while (buf_size > 0) { - len = f->end - rptr; - if (len > buf_size) - len = buf_size; - put_buffer(pb, rptr, len); - rptr += len; - if (rptr >= f->end) - rptr = f->buffer; - buf_size -= len; - } - *rptr_ptr = rptr; - return 0; -} - /** * Allocate the payload of a packet and intialized its fields to default values. * diff --git a/libavutil/Makefile b/libavutil/Makefile index 5b78adc..0450414 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -16,9 +16,10 @@ OBJS= mathematics.o \ adler32.o \ log.o \ mem.o \ + fifo.o \ HEADERS = avutil.h common.h mathematics.h integer.h rational.h \ - intfloat_readwrite.h md5.h adler32.h log.h + intfloat_readwrite.h md5.h adler32.h log.h fifo.h NAME=avutil ifeq ($(BUILD_SHARED),yes) diff --git a/libavutil/fifo.c b/libavutil/fifo.c new file mode 100644 index 0000000..7746182 --- /dev/null +++ b/libavutil/fifo.c @@ -0,0 +1,135 @@ +/* + * A very simple circular buffer FIFO implementation + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2006 Roman Shaposhnik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "common.h" +#include "fifo.h" + +int av_fifo_init(AVFifoBuffer *f, int size) +{ + f->buffer = av_malloc(size); + if (!f->buffer) + return -1; + f->end = f->buffer + size; + f->wptr = f->rptr = f->buffer; + return 0; +} + +void av_fifo_free(AVFifoBuffer *f) +{ + av_free(f->buffer); +} + +int av_fifo_size(AVFifoBuffer *f) +{ + int size = f->wptr - f->rptr; + if (size < 0) + size += f->end - f->buffer; + return size; +} + +/** + * Get data from the fifo (returns -1 if not enough data). + */ +int av_fifo_read(AVFifoBuffer *f, uint8_t *buf, int buf_size) +{ + int len; + int size = f->wptr - f->rptr; + if (size < 0) + size += f->end - f->buffer; + + if (size < buf_size) + return -1; + while (buf_size > 0) { + len = FFMIN(f->end - f->rptr, buf_size); + memcpy(buf, f->rptr, len); + buf += len; + f->rptr += len; + if (f->rptr >= f->end) + f->rptr = f->buffer; + buf_size -= len; + } + return 0; +} + +/** + * Resizes a FIFO. + */ +void av_fifo_realloc(AVFifoBuffer *f, unsigned int new_size) { + unsigned int old_size= f->end - f->buffer; + + if(old_size < new_size){ + uint8_t *old= f->buffer; + + f->buffer= av_realloc(f->buffer, new_size); + + f->rptr += f->buffer - old; + f->wptr += f->buffer - old; + + if(f->wptr < f->rptr){ + memmove(f->rptr + new_size - old_size, f->rptr, f->buffer + old_size - f->rptr); + f->rptr += new_size - old_size; + } + f->end= f->buffer + new_size; + } +} + +void av_fifo_write(AVFifoBuffer *f, const uint8_t *buf, int size) +{ + int len; + + while (size > 0) { + len = FFMIN(f->end - f->wptr, size); + memcpy(f->wptr, buf, len); + f->wptr += len; + if (f->wptr >= f->end) + f->wptr = f->buffer; + buf += len; + size -= len; + } +} + + +/* get data from the fifo (return -1 if not enough data) */ +int av_fifo_generic_read(AVFifoBuffer *f, int buf_size, void (*func)(void*, void*, int), void* dest) +{ + int len; + int size = f->wptr - f->rptr; + if (size < 0) + size += f->end - f->buffer; + + if (size < buf_size) + return -1; + while (buf_size > 0) { + len = FFMIN(f->end - f->rptr, buf_size); + func(dest, f->rptr, len); + f->rptr += len; + if (f->rptr >= f->end) + f->rptr = f->buffer; + buf_size -= len; + } + return 0; +} + +/* discard data from the fifo */ +void av_fifo_drain(AVFifoBuffer *f, int size) +{ + f->rptr += size; + if (f->rptr >= f->end) + f->rptr -= f->end - f->buffer; +} diff --git a/libavutil/fifo.h b/libavutil/fifo.h new file mode 100644 index 0000000..9dec0e6 --- /dev/null +++ b/libavutil/fifo.h @@ -0,0 +1,25 @@ +#ifndef FIFO_H +#define FIFO_H + +typedef struct AVFifoBuffer { + uint8_t *buffer; + uint8_t *rptr, *wptr, *end; +} AVFifoBuffer; + +int av_fifo_init(AVFifoBuffer *f, int size); +void av_fifo_free(AVFifoBuffer *f); +int av_fifo_size(AVFifoBuffer *f); +int av_fifo_read(AVFifoBuffer *f, uint8_t *buf, int buf_size); +int av_fifo_generic_read(AVFifoBuffer *f, int buf_size, void (*func)(void*, void*, int), void* dest); +void av_fifo_write(AVFifoBuffer *f, const uint8_t *buf, int size); +void av_fifo_realloc(AVFifoBuffer *f, unsigned int size); +void av_fifo_drain(AVFifoBuffer *f, int size); + +static inline uint8_t av_fifo_peek(AVFifoBuffer *f, int offs) +{ + uint8_t *ptr = f->rptr + offs; + if (ptr >= f->end) + ptr -= f->end - f->buffer; + return *ptr; +} +#endif /* FIFO_H */ -- 2.7.4