audio_fifo.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Audio FIFO
  3. * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
  4. *
  5. * This file is part of Libav.
  6. *
  7. * Libav 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. * Libav 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 Libav; 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 "fifo.h"
  28. #include "mem.h"
  29. #include "samplefmt.h"
  30. struct AVAudioFifo {
  31. AVFifoBuffer **buf; /**< single buffer for interleaved, per-channel buffers for planar */
  32. int nb_buffers; /**< number of buffers */
  33. int nb_samples; /**< number of samples currently in the FIFO */
  34. int allocated_samples; /**< current allocated size, in samples */
  35. int channels; /**< number of channels */
  36. enum AVSampleFormat sample_fmt; /**< sample format */
  37. int sample_size; /**< size, in bytes, of one sample in a buffer */
  38. };
  39. void av_audio_fifo_free(AVAudioFifo *af)
  40. {
  41. if (af) {
  42. if (af->buf) {
  43. int i;
  44. for (i = 0; i < af->nb_buffers; i++) {
  45. if (af->buf[i])
  46. av_fifo_free(af->buf[i]);
  47. }
  48. av_free(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(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_read(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_read(af->buf[i], data[i], size, NULL)) < 0)
  128. return AVERROR_BUG;
  129. }
  130. af->nb_samples -= nb_samples;
  131. return nb_samples;
  132. }
  133. int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
  134. {
  135. int i, size;
  136. if (nb_samples < 0)
  137. return AVERROR(EINVAL);
  138. nb_samples = FFMIN(nb_samples, af->nb_samples);
  139. if (nb_samples) {
  140. size = nb_samples * af->sample_size;
  141. for (i = 0; i < af->nb_buffers; i++)
  142. av_fifo_drain(af->buf[i], size);
  143. af->nb_samples -= nb_samples;
  144. }
  145. return 0;
  146. }
  147. void av_audio_fifo_reset(AVAudioFifo *af)
  148. {
  149. int i;
  150. for (i = 0; i < af->nb_buffers; i++)
  151. av_fifo_reset(af->buf[i]);
  152. af->nb_samples = 0;
  153. }
  154. int av_audio_fifo_size(AVAudioFifo *af)
  155. {
  156. return af->nb_samples;
  157. }
  158. int av_audio_fifo_space(AVAudioFifo *af)
  159. {
  160. return af->allocated_samples - af->nb_samples;
  161. }