00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "avutil.h"
00028 #include "audio_fifo.h"
00029 #include "fifo.h"
00030 #include "mem.h"
00031 #include "samplefmt.h"
00032
00033 struct AVAudioFifo {
00034 AVFifoBuffer **buf;
00035 int nb_buffers;
00036 int nb_samples;
00037 int allocated_samples;
00039 int channels;
00040 enum AVSampleFormat sample_fmt;
00041 int sample_size;
00042 };
00043
00044 void av_audio_fifo_free(AVAudioFifo *af)
00045 {
00046 if (af) {
00047 if (af->buf) {
00048 int i;
00049 for (i = 0; i < af->nb_buffers; i++) {
00050 if (af->buf[i])
00051 av_fifo_free(af->buf[i]);
00052 }
00053 av_free(af->buf);
00054 }
00055 av_free(af);
00056 }
00057 }
00058
00059 AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
00060 int nb_samples)
00061 {
00062 AVAudioFifo *af;
00063 int buf_size, i;
00064
00065
00066 if (av_samples_get_buffer_size(&buf_size, channels, nb_samples, sample_fmt, 1) < 0)
00067 return NULL;
00068
00069 af = av_mallocz(sizeof(*af));
00070 if (!af)
00071 return NULL;
00072
00073 af->channels = channels;
00074 af->sample_fmt = sample_fmt;
00075 af->sample_size = buf_size / nb_samples;
00076 af->nb_buffers = av_sample_fmt_is_planar(sample_fmt) ? channels : 1;
00077
00078 af->buf = av_mallocz(af->nb_buffers * sizeof(*af->buf));
00079 if (!af->buf)
00080 goto error;
00081
00082 for (i = 0; i < af->nb_buffers; i++) {
00083 af->buf[i] = av_fifo_alloc(buf_size);
00084 if (!af->buf[i])
00085 goto error;
00086 }
00087 af->allocated_samples = nb_samples;
00088
00089 return af;
00090
00091 error:
00092 av_audio_fifo_free(af);
00093 return NULL;
00094 }
00095
00096 int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples)
00097 {
00098 int i, ret, buf_size;
00099
00100 if ((ret = av_samples_get_buffer_size(&buf_size, af->channels, nb_samples,
00101 af->sample_fmt, 1)) < 0)
00102 return ret;
00103
00104 for (i = 0; i < af->nb_buffers; i++) {
00105 if ((ret = av_fifo_realloc2(af->buf[i], buf_size)) < 0)
00106 return ret;
00107 }
00108 af->allocated_samples = nb_samples;
00109 return 0;
00110 }
00111
00112 int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
00113 {
00114 int i, ret, size;
00115
00116
00117 if (av_audio_fifo_space(af) < nb_samples) {
00118 int current_size = av_audio_fifo_size(af);
00119
00120 if (INT_MAX / 2 - current_size < nb_samples)
00121 return AVERROR(EINVAL);
00122
00123 if ((ret = av_audio_fifo_realloc(af, 2 * (current_size + nb_samples))) < 0)
00124 return ret;
00125 }
00126
00127 size = nb_samples * af->sample_size;
00128 for (i = 0; i < af->nb_buffers; i++) {
00129 ret = av_fifo_generic_write(af->buf[i], data[i], size, NULL);
00130 if (ret != size)
00131 return AVERROR_BUG;
00132 }
00133 af->nb_samples += nb_samples;
00134
00135 return nb_samples;
00136 }
00137
00138 int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
00139 {
00140 int i, ret, size;
00141
00142 if (nb_samples < 0)
00143 return AVERROR(EINVAL);
00144 nb_samples = FFMIN(nb_samples, af->nb_samples);
00145 if (!nb_samples)
00146 return 0;
00147
00148 size = nb_samples * af->sample_size;
00149 for (i = 0; i < af->nb_buffers; i++) {
00150 if ((ret = av_fifo_generic_read(af->buf[i], data[i], size, NULL)) < 0)
00151 return AVERROR_BUG;
00152 }
00153 af->nb_samples -= nb_samples;
00154
00155 return nb_samples;
00156 }
00157
00158 int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
00159 {
00160 int i, size;
00161
00162 if (nb_samples < 0)
00163 return AVERROR(EINVAL);
00164 nb_samples = FFMIN(nb_samples, af->nb_samples);
00165
00166 if (nb_samples) {
00167 size = nb_samples * af->sample_size;
00168 for (i = 0; i < af->nb_buffers; i++)
00169 av_fifo_drain(af->buf[i], size);
00170 af->nb_samples -= nb_samples;
00171 }
00172 return 0;
00173 }
00174
00175 void av_audio_fifo_reset(AVAudioFifo *af)
00176 {
00177 int i;
00178
00179 for (i = 0; i < af->nb_buffers; i++)
00180 av_fifo_reset(af->buf[i]);
00181
00182 af->nb_samples = 0;
00183 }
00184
00185 int av_audio_fifo_size(AVAudioFifo *af)
00186 {
00187 return af->nb_samples;
00188 }
00189
00190 int av_audio_fifo_space(AVAudioFifo *af)
00191 {
00192 return af->allocated_samples - af->nb_samples;
00193 }