audio_fifo.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 "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_free(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(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_read(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_read(af->buf[i], data[i], size, NULL)) < 0)
  129. return AVERROR_BUG;
  130. }
  131. af->nb_samples -= nb_samples;
  132. return nb_samples;
  133. }
  134. int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
  135. {
  136. int i, size;
  137. if (nb_samples < 0)
  138. return AVERROR(EINVAL);
  139. nb_samples = FFMIN(nb_samples, af->nb_samples);
  140. if (nb_samples) {
  141. size = nb_samples * af->sample_size;
  142. for (i = 0; i < af->nb_buffers; i++)
  143. av_fifo_drain(af->buf[i], size);
  144. af->nb_samples -= nb_samples;
  145. }
  146. return 0;
  147. }
  148. void av_audio_fifo_reset(AVAudioFifo *af)
  149. {
  150. int i;
  151. for (i = 0; i < af->nb_buffers; i++)
  152. av_fifo_reset(af->buf[i]);
  153. af->nb_samples = 0;
  154. }
  155. int av_audio_fifo_size(AVAudioFifo *af)
  156. {
  157. return af->nb_samples;
  158. }
  159. int av_audio_fifo_space(AVAudioFifo *af)
  160. {
  161. return af->allocated_samples - af->nb_samples;
  162. }