audio_fifo.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Audio FIFO
  3. * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * Audio FIFO
  24. */
  25. #include "avutil.h"
  26. #include "audio_fifo.h"
  27. #include "common.h"
  28. #include "fifo.h"
  29. #include "mem.h"
  30. #include "samplefmt.h"
  31. struct AVAudioFifo {
  32. AVFifoBuffer **buf; /**< single buffer for interleaved, per-channel buffers for planar */
  33. int nb_buffers; /**< number of buffers */
  34. int nb_samples; /**< number of samples currently in the FIFO */
  35. int allocated_samples; /**< current allocated size, in samples */
  36. int channels; /**< number of channels */
  37. enum AVSampleFormat sample_fmt; /**< sample format */
  38. int sample_size; /**< size, in bytes, of one sample in a buffer */
  39. };
  40. void av_audio_fifo_free(AVAudioFifo *af)
  41. {
  42. if (af) {
  43. if (af->buf) {
  44. int i;
  45. for (i = 0; i < af->nb_buffers; i++) {
  46. av_fifo_freep(&af->buf[i]);
  47. }
  48. av_freep(&af->buf);
  49. }
  50. av_free(af);
  51. }
  52. }
  53. AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
  54. int nb_samples)
  55. {
  56. AVAudioFifo *af;
  57. int buf_size, i;
  58. /* get channel buffer size (also validates parameters) */
  59. if (av_samples_get_buffer_size(&buf_size, channels, nb_samples, sample_fmt, 1) < 0)
  60. return NULL;
  61. af = av_mallocz(sizeof(*af));
  62. if (!af)
  63. return NULL;
  64. af->channels = channels;
  65. af->sample_fmt = sample_fmt;
  66. af->sample_size = buf_size / nb_samples;
  67. af->nb_buffers = av_sample_fmt_is_planar(sample_fmt) ? channels : 1;
  68. af->buf = av_mallocz_array(af->nb_buffers, sizeof(*af->buf));
  69. if (!af->buf)
  70. goto error;
  71. for (i = 0; i < af->nb_buffers; i++) {
  72. af->buf[i] = av_fifo_alloc(buf_size);
  73. if (!af->buf[i])
  74. goto error;
  75. }
  76. af->allocated_samples = nb_samples;
  77. return af;
  78. error:
  79. av_audio_fifo_free(af);
  80. return NULL;
  81. }
  82. int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples)
  83. {
  84. int i, ret, buf_size;
  85. if ((ret = av_samples_get_buffer_size(&buf_size, af->channels, nb_samples,
  86. af->sample_fmt, 1)) < 0)
  87. return ret;
  88. for (i = 0; i < af->nb_buffers; i++) {
  89. if ((ret = av_fifo_realloc2(af->buf[i], buf_size)) < 0)
  90. return ret;
  91. }
  92. af->allocated_samples = nb_samples;
  93. return 0;
  94. }
  95. int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
  96. {
  97. int i, ret, size;
  98. /* automatically reallocate buffers if needed */
  99. if (av_audio_fifo_space(af) < nb_samples) {
  100. int current_size = av_audio_fifo_size(af);
  101. /* check for integer overflow in new size calculation */
  102. if (INT_MAX / 2 - current_size < nb_samples)
  103. return AVERROR(EINVAL);
  104. /* reallocate buffers */
  105. if ((ret = av_audio_fifo_realloc(af, 2 * (current_size + nb_samples))) < 0)
  106. return ret;
  107. }
  108. size = nb_samples * af->sample_size;
  109. for (i = 0; i < af->nb_buffers; i++) {
  110. ret = av_fifo_generic_write(af->buf[i], data[i], size, NULL);
  111. if (ret != size)
  112. return AVERROR_BUG;
  113. }
  114. af->nb_samples += nb_samples;
  115. return nb_samples;
  116. }
  117. int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples)
  118. {
  119. int i, ret, size;
  120. if (nb_samples < 0)
  121. return AVERROR(EINVAL);
  122. nb_samples = FFMIN(nb_samples, af->nb_samples);
  123. if (!nb_samples)
  124. return 0;
  125. size = nb_samples * af->sample_size;
  126. for (i = 0; i < af->nb_buffers; i++) {
  127. if ((ret = av_fifo_generic_peek(af->buf[i], data[i], size, NULL)) < 0)
  128. return AVERROR_BUG;
  129. }
  130. return nb_samples;
  131. }
  132. int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset)
  133. {
  134. int i, ret, size;
  135. if (offset < 0 || offset >= af->nb_samples)
  136. return AVERROR(EINVAL);
  137. if (nb_samples < 0)
  138. return AVERROR(EINVAL);
  139. nb_samples = FFMIN(nb_samples, af->nb_samples);
  140. if (!nb_samples)
  141. return 0;
  142. if (offset > af->nb_samples - nb_samples)
  143. return AVERROR(EINVAL);
  144. offset *= af->sample_size;
  145. size = nb_samples * af->sample_size;
  146. for (i = 0; i < af->nb_buffers; i++) {
  147. if ((ret = av_fifo_generic_peek_at(af->buf[i], data[i], offset, size, NULL)) < 0)
  148. return AVERROR_BUG;
  149. }
  150. return nb_samples;
  151. }
  152. int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
  153. {
  154. int i, ret, size;
  155. if (nb_samples < 0)
  156. return AVERROR(EINVAL);
  157. nb_samples = FFMIN(nb_samples, af->nb_samples);
  158. if (!nb_samples)
  159. return 0;
  160. size = nb_samples * af->sample_size;
  161. for (i = 0; i < af->nb_buffers; i++) {
  162. if ((ret = av_fifo_generic_read(af->buf[i], data[i], size, NULL)) < 0)
  163. return AVERROR_BUG;
  164. }
  165. af->nb_samples -= nb_samples;
  166. return nb_samples;
  167. }
  168. int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
  169. {
  170. int i, size;
  171. if (nb_samples < 0)
  172. return AVERROR(EINVAL);
  173. nb_samples = FFMIN(nb_samples, af->nb_samples);
  174. if (nb_samples) {
  175. size = nb_samples * af->sample_size;
  176. for (i = 0; i < af->nb_buffers; i++)
  177. av_fifo_drain(af->buf[i], size);
  178. af->nb_samples -= nb_samples;
  179. }
  180. return 0;
  181. }
  182. void av_audio_fifo_reset(AVAudioFifo *af)
  183. {
  184. int i;
  185. for (i = 0; i < af->nb_buffers; i++)
  186. av_fifo_reset(af->buf[i]);
  187. af->nb_samples = 0;
  188. }
  189. int av_audio_fifo_size(AVAudioFifo *af)
  190. {
  191. return af->nb_samples;
  192. }
  193. int av_audio_fifo_space(AVAudioFifo *af)
  194. {
  195. return af->allocated_samples - af->nb_samples;
  196. }