audio_data.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include <stdint.h>
  21. #include <string.h>
  22. #include "libavutil/mem.h"
  23. #include "audio_data.h"
  24. static const AVClass audio_data_class = {
  25. .class_name = "AudioData",
  26. .item_name = av_default_item_name,
  27. .version = LIBAVUTIL_VERSION_INT,
  28. };
  29. /*
  30. * Calculate alignment for data pointers.
  31. */
  32. static void calc_ptr_alignment(AudioData *a)
  33. {
  34. int p;
  35. int min_align = 128;
  36. for (p = 0; p < a->planes; p++) {
  37. int cur_align = 128;
  38. while ((intptr_t)a->data[p] % cur_align)
  39. cur_align >>= 1;
  40. if (cur_align < min_align)
  41. min_align = cur_align;
  42. }
  43. a->ptr_align = min_align;
  44. }
  45. int ff_audio_data_set_channels(AudioData *a, int channels)
  46. {
  47. if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
  48. channels > a->allocated_channels)
  49. return AVERROR(EINVAL);
  50. a->channels = channels;
  51. a->planes = a->is_planar ? channels : 1;
  52. calc_ptr_alignment(a);
  53. return 0;
  54. }
  55. int ff_audio_data_init(AudioData *a, uint8_t **src, int plane_size, int channels,
  56. int nb_samples, enum AVSampleFormat sample_fmt,
  57. int read_only, const char *name)
  58. {
  59. int p;
  60. memset(a, 0, sizeof(*a));
  61. a->class = &audio_data_class;
  62. if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
  63. av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
  64. return AVERROR(EINVAL);
  65. }
  66. a->sample_size = av_get_bytes_per_sample(sample_fmt);
  67. if (!a->sample_size) {
  68. av_log(a, AV_LOG_ERROR, "invalid sample format\n");
  69. return AVERROR(EINVAL);
  70. }
  71. a->is_planar = av_sample_fmt_is_planar(sample_fmt);
  72. a->planes = a->is_planar ? channels : 1;
  73. a->stride = a->sample_size * (a->is_planar ? 1 : channels);
  74. for (p = 0; p < (a->is_planar ? channels : 1); p++) {
  75. if (!src[p]) {
  76. av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
  77. return AVERROR(EINVAL);
  78. }
  79. a->data[p] = src[p];
  80. }
  81. a->allocated_samples = nb_samples * !read_only;
  82. a->nb_samples = nb_samples;
  83. a->sample_fmt = sample_fmt;
  84. a->channels = channels;
  85. a->allocated_channels = channels;
  86. a->read_only = read_only;
  87. a->allow_realloc = 0;
  88. a->name = name ? name : "{no name}";
  89. calc_ptr_alignment(a);
  90. a->samples_align = plane_size / a->stride;
  91. return 0;
  92. }
  93. AudioData *ff_audio_data_alloc(int channels, int nb_samples,
  94. enum AVSampleFormat sample_fmt, const char *name)
  95. {
  96. AudioData *a;
  97. int ret;
  98. if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
  99. return NULL;
  100. a = av_mallocz(sizeof(*a));
  101. if (!a)
  102. return NULL;
  103. a->sample_size = av_get_bytes_per_sample(sample_fmt);
  104. if (!a->sample_size) {
  105. av_free(a);
  106. return NULL;
  107. }
  108. a->is_planar = av_sample_fmt_is_planar(sample_fmt);
  109. a->planes = a->is_planar ? channels : 1;
  110. a->stride = a->sample_size * (a->is_planar ? 1 : channels);
  111. a->class = &audio_data_class;
  112. a->sample_fmt = sample_fmt;
  113. a->channels = channels;
  114. a->allocated_channels = channels;
  115. a->read_only = 0;
  116. a->allow_realloc = 1;
  117. a->name = name ? name : "{no name}";
  118. if (nb_samples > 0) {
  119. ret = ff_audio_data_realloc(a, nb_samples);
  120. if (ret < 0) {
  121. av_free(a);
  122. return NULL;
  123. }
  124. return a;
  125. } else {
  126. calc_ptr_alignment(a);
  127. return a;
  128. }
  129. }
  130. int ff_audio_data_realloc(AudioData *a, int nb_samples)
  131. {
  132. int ret, new_buf_size, plane_size, p;
  133. /* check if buffer is already large enough */
  134. if (a->allocated_samples >= nb_samples)
  135. return 0;
  136. /* validate that the output is not read-only and realloc is allowed */
  137. if (a->read_only || !a->allow_realloc)
  138. return AVERROR(EINVAL);
  139. new_buf_size = av_samples_get_buffer_size(&plane_size,
  140. a->allocated_channels, nb_samples,
  141. a->sample_fmt, 0);
  142. if (new_buf_size < 0)
  143. return new_buf_size;
  144. /* if there is already data in the buffer and the sample format is planar,
  145. allocate a new buffer and copy the data, otherwise just realloc the
  146. internal buffer and set new data pointers */
  147. if (a->nb_samples > 0 && a->is_planar) {
  148. uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
  149. ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
  150. nb_samples, a->sample_fmt, 0);
  151. if (ret < 0)
  152. return ret;
  153. for (p = 0; p < a->planes; p++)
  154. memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
  155. av_freep(&a->buffer);
  156. memcpy(a->data, new_data, sizeof(new_data));
  157. a->buffer = a->data[0];
  158. } else {
  159. av_freep(&a->buffer);
  160. a->buffer = av_malloc(new_buf_size);
  161. if (!a->buffer)
  162. return AVERROR(ENOMEM);
  163. ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
  164. a->allocated_channels, nb_samples,
  165. a->sample_fmt, 0);
  166. if (ret < 0)
  167. return ret;
  168. }
  169. a->buffer_size = new_buf_size;
  170. a->allocated_samples = nb_samples;
  171. calc_ptr_alignment(a);
  172. a->samples_align = plane_size / a->stride;
  173. return 0;
  174. }
  175. void ff_audio_data_free(AudioData **a)
  176. {
  177. if (!*a)
  178. return;
  179. av_free((*a)->buffer);
  180. av_freep(a);
  181. }
  182. int ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map)
  183. {
  184. int ret, p;
  185. /* validate input/output compatibility */
  186. if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
  187. return AVERROR(EINVAL);
  188. if (map && !src->is_planar) {
  189. av_log(src, AV_LOG_ERROR, "cannot remap packed format during copy\n");
  190. return AVERROR(EINVAL);
  191. }
  192. /* if the input is empty, just empty the output */
  193. if (!src->nb_samples) {
  194. dst->nb_samples = 0;
  195. return 0;
  196. }
  197. /* reallocate output if necessary */
  198. ret = ff_audio_data_realloc(dst, src->nb_samples);
  199. if (ret < 0)
  200. return ret;
  201. /* copy data */
  202. if (map) {
  203. if (map->do_remap) {
  204. for (p = 0; p < src->planes; p++) {
  205. if (map->channel_map[p] >= 0)
  206. memcpy(dst->data[p], src->data[map->channel_map[p]],
  207. src->nb_samples * src->stride);
  208. }
  209. }
  210. if (map->do_copy || map->do_zero) {
  211. for (p = 0; p < src->planes; p++) {
  212. if (map->channel_copy[p])
  213. memcpy(dst->data[p], dst->data[map->channel_copy[p]],
  214. src->nb_samples * src->stride);
  215. else if (map->channel_zero[p])
  216. av_samples_set_silence(&dst->data[p], 0, src->nb_samples,
  217. 1, dst->sample_fmt);
  218. }
  219. }
  220. } else {
  221. for (p = 0; p < src->planes; p++)
  222. memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
  223. }
  224. dst->nb_samples = src->nb_samples;
  225. return 0;
  226. }
  227. int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
  228. int src_offset, int nb_samples)
  229. {
  230. int ret, p, dst_offset2, dst_move_size;
  231. /* validate input/output compatibility */
  232. if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
  233. av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
  234. return AVERROR(EINVAL);
  235. }
  236. /* validate offsets are within the buffer bounds */
  237. if (dst_offset < 0 || dst_offset > dst->nb_samples ||
  238. src_offset < 0 || src_offset > src->nb_samples) {
  239. av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
  240. src_offset, dst_offset);
  241. return AVERROR(EINVAL);
  242. }
  243. /* check offsets and sizes to see if we can just do nothing and return */
  244. if (nb_samples > src->nb_samples - src_offset)
  245. nb_samples = src->nb_samples - src_offset;
  246. if (nb_samples <= 0)
  247. return 0;
  248. /* validate that the output is not read-only */
  249. if (dst->read_only) {
  250. av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
  251. return AVERROR(EINVAL);
  252. }
  253. /* reallocate output if necessary */
  254. ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
  255. if (ret < 0) {
  256. av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
  257. return ret;
  258. }
  259. dst_offset2 = dst_offset + nb_samples;
  260. dst_move_size = dst->nb_samples - dst_offset;
  261. for (p = 0; p < src->planes; p++) {
  262. if (dst_move_size > 0) {
  263. memmove(dst->data[p] + dst_offset2 * dst->stride,
  264. dst->data[p] + dst_offset * dst->stride,
  265. dst_move_size * dst->stride);
  266. }
  267. memcpy(dst->data[p] + dst_offset * dst->stride,
  268. src->data[p] + src_offset * src->stride,
  269. nb_samples * src->stride);
  270. }
  271. dst->nb_samples += nb_samples;
  272. return 0;
  273. }
  274. void ff_audio_data_drain(AudioData *a, int nb_samples)
  275. {
  276. if (a->nb_samples <= nb_samples) {
  277. /* drain the whole buffer */
  278. a->nb_samples = 0;
  279. } else {
  280. int p;
  281. int move_offset = a->stride * nb_samples;
  282. int move_size = a->stride * (a->nb_samples - nb_samples);
  283. for (p = 0; p < a->planes; p++)
  284. memmove(a->data[p], a->data[p] + move_offset, move_size);
  285. a->nb_samples -= nb_samples;
  286. }
  287. }
  288. int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
  289. int nb_samples)
  290. {
  291. uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
  292. int offset_size, p;
  293. if (offset >= a->nb_samples)
  294. return 0;
  295. offset_size = offset * a->stride;
  296. for (p = 0; p < a->planes; p++)
  297. offset_data[p] = a->data[p] + offset_size;
  298. return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
  299. }
  300. int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
  301. {
  302. int ret;
  303. if (a->read_only)
  304. return AVERROR(EINVAL);
  305. ret = ff_audio_data_realloc(a, nb_samples);
  306. if (ret < 0)
  307. return ret;
  308. ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
  309. if (ret >= 0)
  310. a->nb_samples = ret;
  311. return ret;
  312. }