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