Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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