audio_fifo.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <inttypes.h>
  21. #include "libavutil/mem.h"
  22. #include "libavutil/audio_fifo.c"
  23. #define MAX_CHANNELS 32
  24. typedef struct TestStruct {
  25. const enum AVSampleFormat format;
  26. const int nb_ch;
  27. void const *data_planes[MAX_CHANNELS];
  28. const int nb_samples_pch;
  29. } TestStruct;
  30. static const uint8_t data_U8 [] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
  31. static const int16_t data_S16[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
  32. static const float data_FLT[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0};
  33. static const TestStruct test_struct[] = {
  34. {.format = AV_SAMPLE_FMT_U8 , .nb_ch = 1, .data_planes = {data_U8 , }, .nb_samples_pch = 12},
  35. {.format = AV_SAMPLE_FMT_U8P , .nb_ch = 2, .data_planes = {data_U8 , data_U8 +6, }, .nb_samples_pch = 6 },
  36. {.format = AV_SAMPLE_FMT_S16 , .nb_ch = 1, .data_planes = {data_S16, }, .nb_samples_pch = 12},
  37. {.format = AV_SAMPLE_FMT_S16P , .nb_ch = 2, .data_planes = {data_S16, data_S16+6, }, .nb_samples_pch = 6 },
  38. {.format = AV_SAMPLE_FMT_FLT , .nb_ch = 1, .data_planes = {data_FLT, }, .nb_samples_pch = 12},
  39. {.format = AV_SAMPLE_FMT_FLTP , .nb_ch = 2, .data_planes = {data_FLT, data_FLT+6, }, .nb_samples_pch = 6 }
  40. };
  41. static void free_data_planes(AVAudioFifo *afifo, void **output_data)
  42. {
  43. int i;
  44. for (i = 0; i < afifo->nb_buffers; ++i){
  45. av_freep(&output_data[i]);
  46. }
  47. av_freep(&output_data);
  48. }
  49. static void ERROR(const char *str)
  50. {
  51. fprintf(stderr, "%s\n", str);
  52. exit(1);
  53. }
  54. static void print_audio_bytes(const TestStruct *test_sample, void **data_planes, int nb_samples)
  55. {
  56. int p, b, f;
  57. int byte_offset = av_get_bytes_per_sample(test_sample->format);
  58. int buffers = av_sample_fmt_is_planar(test_sample->format)
  59. ? test_sample->nb_ch : 1;
  60. int line_size = (buffers > 1) ? nb_samples * byte_offset
  61. : nb_samples * byte_offset * test_sample->nb_ch;
  62. for (p = 0; p < buffers; ++p){
  63. for(b = 0; b < line_size; b+=byte_offset){
  64. for (f = 0; f < byte_offset; f++){
  65. int order = !HAVE_BIGENDIAN ? (byte_offset - f - 1) : f;
  66. printf("%02x", *((uint8_t*)data_planes[p] + b + order));
  67. }
  68. putchar(' ');
  69. }
  70. putchar('\n');
  71. }
  72. }
  73. static int read_samples_from_audio_fifo(AVAudioFifo* afifo, void ***output, int nb_samples)
  74. {
  75. int i;
  76. int samples = FFMIN(nb_samples, afifo->nb_samples);
  77. int tot_elements = !av_sample_fmt_is_planar(afifo->sample_fmt)
  78. ? samples : afifo->channels * samples;
  79. void **data_planes = av_malloc_array(afifo->nb_buffers, sizeof(void*));
  80. if (!data_planes)
  81. ERROR("failed to allocate memory!");
  82. if (*output)
  83. free_data_planes(afifo, *output);
  84. *output = data_planes;
  85. for (i = 0; i < afifo->nb_buffers; ++i){
  86. data_planes[i] = av_malloc_array(tot_elements, afifo->sample_size);
  87. if (!data_planes[i])
  88. ERROR("failed to allocate memory!");
  89. }
  90. return av_audio_fifo_read(afifo, *output, nb_samples);
  91. }
  92. static int write_samples_to_audio_fifo(AVAudioFifo* afifo, const TestStruct *test_sample,
  93. int nb_samples, int offset)
  94. {
  95. int offset_size, i;
  96. void *data_planes[MAX_CHANNELS];
  97. if(nb_samples > test_sample->nb_samples_pch - offset){
  98. return 0;
  99. }
  100. if(offset >= test_sample->nb_samples_pch){
  101. return 0;
  102. }
  103. offset_size = offset * afifo->sample_size;
  104. for (i = 0; i < afifo->nb_buffers ; ++i){
  105. data_planes[i] = (uint8_t*)test_sample->data_planes[i] + offset_size;
  106. }
  107. return av_audio_fifo_write(afifo, data_planes, nb_samples);
  108. }
  109. static void test_function(const TestStruct *test_sample)
  110. {
  111. int ret, i;
  112. void **output_data = NULL;
  113. AVAudioFifo *afifo = av_audio_fifo_alloc(test_sample->format, test_sample->nb_ch,
  114. test_sample->nb_samples_pch);
  115. if (!afifo) {
  116. ERROR("ERROR: av_audio_fifo_alloc returned NULL!");
  117. }
  118. ret = write_samples_to_audio_fifo(afifo, test_sample, test_sample->nb_samples_pch, 0);
  119. if (ret < 0){
  120. ERROR("ERROR: av_audio_fifo_write failed!");
  121. }
  122. printf("written: %d\n", ret);
  123. ret = write_samples_to_audio_fifo(afifo, test_sample, test_sample->nb_samples_pch, 0);
  124. if (ret < 0){
  125. ERROR("ERROR: av_audio_fifo_write failed!");
  126. }
  127. printf("written: %d\n", ret);
  128. printf("remaining samples in audio_fifo: %d\n\n", av_audio_fifo_size(afifo));
  129. ret = read_samples_from_audio_fifo(afifo, &output_data, test_sample->nb_samples_pch);
  130. if (ret < 0){
  131. ERROR("ERROR: av_audio_fifo_read failed!");
  132. }
  133. printf("read: %d\n", ret);
  134. print_audio_bytes(test_sample, output_data, ret);
  135. printf("remaining samples in audio_fifo: %d\n\n", av_audio_fifo_size(afifo));
  136. /* test av_audio_fifo_peek */
  137. ret = av_audio_fifo_peek(afifo, output_data, afifo->nb_samples);
  138. if (ret < 0){
  139. ERROR("ERROR: av_audio_fifo_peek failed!");
  140. }
  141. printf("peek:\n");
  142. print_audio_bytes(test_sample, output_data, ret);
  143. printf("\n");
  144. /* test av_audio_fifo_peek_at */
  145. printf("peek_at:\n");
  146. for (i = 0; i < afifo->nb_samples; ++i){
  147. ret = av_audio_fifo_peek_at(afifo, output_data, 1, i);
  148. if (ret < 0){
  149. ERROR("ERROR: av_audio_fifo_peek_at failed!");
  150. }
  151. printf("%d:\n", i);
  152. print_audio_bytes(test_sample, output_data, ret);
  153. }
  154. printf("\n");
  155. /* test av_audio_fifo_drain */
  156. ret = av_audio_fifo_drain(afifo, afifo->nb_samples);
  157. if (ret < 0){
  158. ERROR("ERROR: av_audio_fifo_drain failed!");
  159. }
  160. if (afifo->nb_samples){
  161. ERROR("drain failed to flush all samples in audio_fifo!");
  162. }
  163. /* deallocate */
  164. free_data_planes(afifo, output_data);
  165. av_audio_fifo_free(afifo);
  166. }
  167. int main(void)
  168. {
  169. int t, tests = sizeof(test_struct)/sizeof(test_struct[0]);
  170. for (t = 0; t < tests; ++t){
  171. printf("\nTEST: %d\n\n", t+1);
  172. test_function(&test_struct[t]);
  173. }
  174. return 0;
  175. }