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.

382 lines
11KB

  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_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels)
  46. {
  47. if (channels == 1)
  48. return 1;
  49. else
  50. return av_sample_fmt_is_planar(sample_fmt);
  51. }
  52. int ff_audio_data_set_channels(AudioData *a, int channels)
  53. {
  54. if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
  55. channels > a->allocated_channels)
  56. return AVERROR(EINVAL);
  57. a->channels = channels;
  58. a->planes = a->is_planar ? channels : 1;
  59. calc_ptr_alignment(a);
  60. return 0;
  61. }
  62. int ff_audio_data_init(AudioData *a, uint8_t * const *src, int plane_size,
  63. int channels, int nb_samples,
  64. enum AVSampleFormat sample_fmt, int read_only,
  65. const char *name)
  66. {
  67. int p;
  68. memset(a, 0, sizeof(*a));
  69. a->class = &audio_data_class;
  70. if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
  71. av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
  72. return AVERROR(EINVAL);
  73. }
  74. a->sample_size = av_get_bytes_per_sample(sample_fmt);
  75. if (!a->sample_size) {
  76. av_log(a, AV_LOG_ERROR, "invalid sample format\n");
  77. return AVERROR(EINVAL);
  78. }
  79. a->is_planar = ff_sample_fmt_is_planar(sample_fmt, channels);
  80. a->planes = a->is_planar ? channels : 1;
  81. a->stride = a->sample_size * (a->is_planar ? 1 : channels);
  82. for (p = 0; p < (a->is_planar ? channels : 1); p++) {
  83. if (!src[p]) {
  84. av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
  85. return AVERROR(EINVAL);
  86. }
  87. a->data[p] = src[p];
  88. }
  89. a->allocated_samples = nb_samples * !read_only;
  90. a->nb_samples = nb_samples;
  91. a->sample_fmt = sample_fmt;
  92. a->channels = channels;
  93. a->allocated_channels = channels;
  94. a->read_only = read_only;
  95. a->allow_realloc = 0;
  96. a->name = name ? name : "{no name}";
  97. calc_ptr_alignment(a);
  98. a->samples_align = plane_size / a->stride;
  99. return 0;
  100. }
  101. AudioData *ff_audio_data_alloc(int channels, int nb_samples,
  102. enum AVSampleFormat sample_fmt, const char *name)
  103. {
  104. AudioData *a;
  105. int ret;
  106. if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
  107. return NULL;
  108. a = av_mallocz(sizeof(*a));
  109. if (!a)
  110. return NULL;
  111. a->sample_size = av_get_bytes_per_sample(sample_fmt);
  112. if (!a->sample_size) {
  113. av_free(a);
  114. return NULL;
  115. }
  116. a->is_planar = ff_sample_fmt_is_planar(sample_fmt, channels);
  117. a->planes = a->is_planar ? channels : 1;
  118. a->stride = a->sample_size * (a->is_planar ? 1 : channels);
  119. a->class = &audio_data_class;
  120. a->sample_fmt = sample_fmt;
  121. a->channels = channels;
  122. a->allocated_channels = channels;
  123. a->read_only = 0;
  124. a->allow_realloc = 1;
  125. a->name = name ? name : "{no name}";
  126. if (nb_samples > 0) {
  127. ret = ff_audio_data_realloc(a, nb_samples);
  128. if (ret < 0) {
  129. av_free(a);
  130. return NULL;
  131. }
  132. return a;
  133. } else {
  134. calc_ptr_alignment(a);
  135. return a;
  136. }
  137. }
  138. int ff_audio_data_realloc(AudioData *a, int nb_samples)
  139. {
  140. int ret, new_buf_size, plane_size, p;
  141. /* check if buffer is already large enough */
  142. if (a->allocated_samples >= nb_samples)
  143. return 0;
  144. /* validate that the output is not read-only and realloc is allowed */
  145. if (a->read_only || !a->allow_realloc)
  146. return AVERROR(EINVAL);
  147. new_buf_size = av_samples_get_buffer_size(&plane_size,
  148. a->allocated_channels, nb_samples,
  149. a->sample_fmt, 0);
  150. if (new_buf_size < 0)
  151. return new_buf_size;
  152. /* if there is already data in the buffer and the sample format is planar,
  153. allocate a new buffer and copy the data, otherwise just realloc the
  154. internal buffer and set new data pointers */
  155. if (a->nb_samples > 0 && a->is_planar) {
  156. uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
  157. ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
  158. nb_samples, a->sample_fmt, 0);
  159. if (ret < 0)
  160. return ret;
  161. for (p = 0; p < a->planes; p++)
  162. memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
  163. av_freep(&a->buffer);
  164. memcpy(a->data, new_data, sizeof(new_data));
  165. a->buffer = a->data[0];
  166. } else {
  167. av_freep(&a->buffer);
  168. a->buffer = av_malloc(new_buf_size);
  169. if (!a->buffer)
  170. return AVERROR(ENOMEM);
  171. ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
  172. a->allocated_channels, nb_samples,
  173. a->sample_fmt, 0);
  174. if (ret < 0)
  175. return ret;
  176. }
  177. a->buffer_size = new_buf_size;
  178. a->allocated_samples = nb_samples;
  179. calc_ptr_alignment(a);
  180. a->samples_align = plane_size / a->stride;
  181. return 0;
  182. }
  183. void ff_audio_data_free(AudioData **a)
  184. {
  185. if (!*a)
  186. return;
  187. av_free((*a)->buffer);
  188. av_freep(a);
  189. }
  190. int ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map)
  191. {
  192. int ret, p;
  193. /* validate input/output compatibility */
  194. if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
  195. return AVERROR(EINVAL);
  196. if (map && !src->is_planar) {
  197. av_log(src, AV_LOG_ERROR, "cannot remap packed format during copy\n");
  198. return AVERROR(EINVAL);
  199. }
  200. /* if the input is empty, just empty the output */
  201. if (!src->nb_samples) {
  202. dst->nb_samples = 0;
  203. return 0;
  204. }
  205. /* reallocate output if necessary */
  206. ret = ff_audio_data_realloc(dst, src->nb_samples);
  207. if (ret < 0)
  208. return ret;
  209. /* copy data */
  210. if (map) {
  211. if (map->do_remap) {
  212. for (p = 0; p < src->planes; p++) {
  213. if (map->channel_map[p] >= 0)
  214. memcpy(dst->data[p], src->data[map->channel_map[p]],
  215. src->nb_samples * src->stride);
  216. }
  217. }
  218. if (map->do_copy || map->do_zero) {
  219. for (p = 0; p < src->planes; p++) {
  220. if (map->channel_copy[p])
  221. memcpy(dst->data[p], dst->data[map->channel_copy[p]],
  222. src->nb_samples * src->stride);
  223. else if (map->channel_zero[p])
  224. av_samples_set_silence(&dst->data[p], 0, src->nb_samples,
  225. 1, dst->sample_fmt);
  226. }
  227. }
  228. } else {
  229. for (p = 0; p < src->planes; p++)
  230. memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
  231. }
  232. dst->nb_samples = src->nb_samples;
  233. return 0;
  234. }
  235. int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
  236. int src_offset, int nb_samples)
  237. {
  238. int ret, p, dst_offset2, dst_move_size;
  239. /* validate input/output compatibility */
  240. if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
  241. av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
  242. return AVERROR(EINVAL);
  243. }
  244. /* validate offsets are within the buffer bounds */
  245. if (dst_offset < 0 || dst_offset > dst->nb_samples ||
  246. src_offset < 0 || src_offset > src->nb_samples) {
  247. av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
  248. src_offset, dst_offset);
  249. return AVERROR(EINVAL);
  250. }
  251. /* check offsets and sizes to see if we can just do nothing and return */
  252. if (nb_samples > src->nb_samples - src_offset)
  253. nb_samples = src->nb_samples - src_offset;
  254. if (nb_samples <= 0)
  255. return 0;
  256. /* validate that the output is not read-only */
  257. if (dst->read_only) {
  258. av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
  259. return AVERROR(EINVAL);
  260. }
  261. /* reallocate output if necessary */
  262. ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
  263. if (ret < 0) {
  264. av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
  265. return ret;
  266. }
  267. dst_offset2 = dst_offset + nb_samples;
  268. dst_move_size = dst->nb_samples - dst_offset;
  269. for (p = 0; p < src->planes; p++) {
  270. if (dst_move_size > 0) {
  271. memmove(dst->data[p] + dst_offset2 * dst->stride,
  272. dst->data[p] + dst_offset * dst->stride,
  273. dst_move_size * dst->stride);
  274. }
  275. memcpy(dst->data[p] + dst_offset * dst->stride,
  276. src->data[p] + src_offset * src->stride,
  277. nb_samples * src->stride);
  278. }
  279. dst->nb_samples += nb_samples;
  280. return 0;
  281. }
  282. void ff_audio_data_drain(AudioData *a, int nb_samples)
  283. {
  284. if (a->nb_samples <= nb_samples) {
  285. /* drain the whole buffer */
  286. a->nb_samples = 0;
  287. } else {
  288. int p;
  289. int move_offset = a->stride * nb_samples;
  290. int move_size = a->stride * (a->nb_samples - nb_samples);
  291. for (p = 0; p < a->planes; p++)
  292. memmove(a->data[p], a->data[p] + move_offset, move_size);
  293. a->nb_samples -= nb_samples;
  294. }
  295. }
  296. int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
  297. int nb_samples)
  298. {
  299. uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
  300. int offset_size, p;
  301. if (offset >= a->nb_samples)
  302. return 0;
  303. offset_size = offset * a->stride;
  304. for (p = 0; p < a->planes; p++)
  305. offset_data[p] = a->data[p] + offset_size;
  306. return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
  307. }
  308. int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
  309. {
  310. int ret;
  311. if (a->read_only)
  312. return AVERROR(EINVAL);
  313. ret = ff_audio_data_realloc(a, nb_samples);
  314. if (ret < 0)
  315. return ret;
  316. ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
  317. if (ret >= 0)
  318. a->nb_samples = ret;
  319. return ret;
  320. }