You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
6.4KB

  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. if (af->buf[i])
  47. av_fifo_free(af->buf[i]);
  48. }
  49. av_freep(&af->buf);
  50. }
  51. av_free(af);
  52. }
  53. }
  54. AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
  55. int nb_samples)
  56. {
  57. AVAudioFifo *af;
  58. int buf_size, i;
  59. /* get channel buffer size (also validates parameters) */
  60. if (av_samples_get_buffer_size(&buf_size, channels, nb_samples, sample_fmt, 1) < 0)
  61. return NULL;
  62. af = av_mallocz(sizeof(*af));
  63. if (!af)
  64. return NULL;
  65. af->channels = channels;
  66. af->sample_fmt = sample_fmt;
  67. af->sample_size = buf_size / nb_samples;
  68. af->nb_buffers = av_sample_fmt_is_planar(sample_fmt) ? channels : 1;
  69. af->buf = av_mallocz_array(af->nb_buffers, sizeof(*af->buf));
  70. if (!af->buf)
  71. goto error;
  72. for (i = 0; i < af->nb_buffers; i++) {
  73. af->buf[i] = av_fifo_alloc(buf_size);
  74. if (!af->buf[i])
  75. goto error;
  76. }
  77. af->allocated_samples = nb_samples;
  78. return af;
  79. error:
  80. av_audio_fifo_free(af);
  81. return NULL;
  82. }
  83. int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples)
  84. {
  85. int i, ret, buf_size;
  86. if ((ret = av_samples_get_buffer_size(&buf_size, af->channels, nb_samples,
  87. af->sample_fmt, 1)) < 0)
  88. return ret;
  89. for (i = 0; i < af->nb_buffers; i++) {
  90. if ((ret = av_fifo_realloc2(af->buf[i], buf_size)) < 0)
  91. return ret;
  92. }
  93. af->allocated_samples = nb_samples;
  94. return 0;
  95. }
  96. int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
  97. {
  98. int i, ret, size;
  99. /* automatically reallocate buffers if needed */
  100. if (av_audio_fifo_space(af) < nb_samples) {
  101. int current_size = av_audio_fifo_size(af);
  102. /* check for integer overflow in new size calculation */
  103. if (INT_MAX / 2 - current_size < nb_samples)
  104. return AVERROR(EINVAL);
  105. /* reallocate buffers */
  106. if ((ret = av_audio_fifo_realloc(af, 2 * (current_size + nb_samples))) < 0)
  107. return ret;
  108. }
  109. size = nb_samples * af->sample_size;
  110. for (i = 0; i < af->nb_buffers; i++) {
  111. ret = av_fifo_generic_write(af->buf[i], data[i], size, NULL);
  112. if (ret != size)
  113. return AVERROR_BUG;
  114. }
  115. af->nb_samples += nb_samples;
  116. return nb_samples;
  117. }
  118. int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples)
  119. {
  120. int i, ret, size;
  121. if (nb_samples < 0)
  122. return AVERROR(EINVAL);
  123. nb_samples = FFMIN(nb_samples, af->nb_samples);
  124. if (!nb_samples)
  125. return 0;
  126. size = nb_samples * af->sample_size;
  127. for (i = 0; i < af->nb_buffers; i++) {
  128. if ((ret = av_fifo_generic_peek(af->buf[i], data[i], size, NULL)) < 0)
  129. return AVERROR_BUG;
  130. }
  131. return nb_samples;
  132. }
  133. int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset)
  134. {
  135. int i, ret, size;
  136. if (offset < 0 || offset >= af->nb_samples)
  137. return AVERROR(EINVAL);
  138. if (nb_samples < 0)
  139. return AVERROR(EINVAL);
  140. nb_samples = FFMIN(nb_samples, af->nb_samples);
  141. if (!nb_samples)
  142. return 0;
  143. if (offset > af->nb_samples - nb_samples)
  144. return AVERROR(EINVAL);
  145. offset *= af->sample_size;
  146. size = nb_samples * af->sample_size;
  147. for (i = 0; i < af->nb_buffers; i++) {
  148. if ((ret = av_fifo_generic_peek_at(af->buf[i], data[i], offset, size, NULL)) < 0)
  149. return AVERROR_BUG;
  150. }
  151. return nb_samples;
  152. }
  153. int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
  154. {
  155. int i, ret, size;
  156. if (nb_samples < 0)
  157. return AVERROR(EINVAL);
  158. nb_samples = FFMIN(nb_samples, af->nb_samples);
  159. if (!nb_samples)
  160. return 0;
  161. size = nb_samples * af->sample_size;
  162. for (i = 0; i < af->nb_buffers; i++) {
  163. if ((ret = av_fifo_generic_read(af->buf[i], data[i], size, NULL)) < 0)
  164. return AVERROR_BUG;
  165. }
  166. af->nb_samples -= nb_samples;
  167. return nb_samples;
  168. }
  169. int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
  170. {
  171. int i, size;
  172. if (nb_samples < 0)
  173. return AVERROR(EINVAL);
  174. nb_samples = FFMIN(nb_samples, af->nb_samples);
  175. if (nb_samples) {
  176. size = nb_samples * af->sample_size;
  177. for (i = 0; i < af->nb_buffers; i++)
  178. av_fifo_drain(af->buf[i], size);
  179. af->nb_samples -= nb_samples;
  180. }
  181. return 0;
  182. }
  183. void av_audio_fifo_reset(AVAudioFifo *af)
  184. {
  185. int i;
  186. for (i = 0; i < af->nb_buffers; i++)
  187. av_fifo_reset(af->buf[i]);
  188. af->nb_samples = 0;
  189. }
  190. int av_audio_fifo_size(AVAudioFifo *af)
  191. {
  192. return af->nb_samples;
  193. }
  194. int av_audio_fifo_space(AVAudioFifo *af)
  195. {
  196. return af->allocated_samples - af->nb_samples;
  197. }