tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

samplefmt.c (9383B)


      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 
     19 #include "error.h"
     20 #include "macros.h"
     21 #include "mem.h"
     22 #include "samplefmt.h"
     23 
     24 #include <limits.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 
     28 typedef struct SampleFmtInfo {
     29    char name[8];
     30    int bits;
     31    int planar;
     32    enum AVSampleFormat altform; ///< planar<->packed alternative form
     33 } SampleFmtInfo;
     34 
     35 /** this table gives more information about formats */
     36 static const SampleFmtInfo sample_fmt_info[AV_SAMPLE_FMT_NB] = {
     37    [AV_SAMPLE_FMT_U8]   = { .name =   "u8", .bits =  8, .planar = 0, .altform = AV_SAMPLE_FMT_U8P  },
     38    [AV_SAMPLE_FMT_S16]  = { .name =  "s16", .bits = 16, .planar = 0, .altform = AV_SAMPLE_FMT_S16P },
     39    [AV_SAMPLE_FMT_S32]  = { .name =  "s32", .bits = 32, .planar = 0, .altform = AV_SAMPLE_FMT_S32P },
     40    [AV_SAMPLE_FMT_S64]  = { .name =  "s64", .bits = 64, .planar = 0, .altform = AV_SAMPLE_FMT_S64P },
     41    [AV_SAMPLE_FMT_FLT]  = { .name =  "flt", .bits = 32, .planar = 0, .altform = AV_SAMPLE_FMT_FLTP },
     42    [AV_SAMPLE_FMT_DBL]  = { .name =  "dbl", .bits = 64, .planar = 0, .altform = AV_SAMPLE_FMT_DBLP },
     43    [AV_SAMPLE_FMT_U8P]  = { .name =  "u8p", .bits =  8, .planar = 1, .altform = AV_SAMPLE_FMT_U8   },
     44    [AV_SAMPLE_FMT_S16P] = { .name = "s16p", .bits = 16, .planar = 1, .altform = AV_SAMPLE_FMT_S16  },
     45    [AV_SAMPLE_FMT_S32P] = { .name = "s32p", .bits = 32, .planar = 1, .altform = AV_SAMPLE_FMT_S32  },
     46    [AV_SAMPLE_FMT_S64P] = { .name = "s64p", .bits = 64, .planar = 1, .altform = AV_SAMPLE_FMT_S64  },
     47    [AV_SAMPLE_FMT_FLTP] = { .name = "fltp", .bits = 32, .planar = 1, .altform = AV_SAMPLE_FMT_FLT  },
     48    [AV_SAMPLE_FMT_DBLP] = { .name = "dblp", .bits = 64, .planar = 1, .altform = AV_SAMPLE_FMT_DBL  },
     49 };
     50 
     51 const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
     52 {
     53    if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
     54        return NULL;
     55    return sample_fmt_info[sample_fmt].name;
     56 }
     57 
     58 enum AVSampleFormat av_get_sample_fmt(const char *name)
     59 {
     60    int i;
     61 
     62    for (i = 0; i < AV_SAMPLE_FMT_NB; i++)
     63        if (!strcmp(sample_fmt_info[i].name, name))
     64            return i;
     65    return AV_SAMPLE_FMT_NONE;
     66 }
     67 
     68 enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar)
     69 {
     70    if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
     71        return AV_SAMPLE_FMT_NONE;
     72    if (sample_fmt_info[sample_fmt].planar == planar)
     73        return sample_fmt;
     74    return sample_fmt_info[sample_fmt].altform;
     75 }
     76 
     77 enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
     78 {
     79    if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
     80        return AV_SAMPLE_FMT_NONE;
     81    if (sample_fmt_info[sample_fmt].planar)
     82        return sample_fmt_info[sample_fmt].altform;
     83    return sample_fmt;
     84 }
     85 
     86 enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt)
     87 {
     88    if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
     89        return AV_SAMPLE_FMT_NONE;
     90    if (sample_fmt_info[sample_fmt].planar)
     91        return sample_fmt;
     92    return sample_fmt_info[sample_fmt].altform;
     93 }
     94 
     95 char *av_get_sample_fmt_string (char *buf, int buf_size, enum AVSampleFormat sample_fmt)
     96 {
     97    /* print header */
     98    if (sample_fmt < 0)
     99        snprintf(buf, buf_size, "name  " " depth");
    100    else if (sample_fmt < AV_SAMPLE_FMT_NB) {
    101        SampleFmtInfo info = sample_fmt_info[sample_fmt];
    102        snprintf (buf, buf_size, "%-6s" "   %2d ", info.name, info.bits);
    103    }
    104 
    105    return buf;
    106 }
    107 
    108 int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
    109 {
    110     return sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB ?
    111        0 : sample_fmt_info[sample_fmt].bits >> 3;
    112 }
    113 
    114 int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
    115 {
    116     if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
    117         return 0;
    118     return sample_fmt_info[sample_fmt].planar;
    119 }
    120 
    121 int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
    122                               enum AVSampleFormat sample_fmt, int align)
    123 {
    124    int line_size;
    125    int sample_size = av_get_bytes_per_sample(sample_fmt);
    126    int planar      = av_sample_fmt_is_planar(sample_fmt);
    127 
    128    /* validate parameter ranges */
    129    if (!sample_size || nb_samples <= 0 || nb_channels <= 0)
    130        return AVERROR(EINVAL);
    131 
    132    /* auto-select alignment if not specified */
    133    if (!align) {
    134        if (nb_samples > INT_MAX - 31)
    135            return AVERROR(EINVAL);
    136        align = 1;
    137        nb_samples = FFALIGN(nb_samples, 32);
    138    }
    139 
    140    /* check for integer overflow */
    141    if (nb_channels > INT_MAX / align ||
    142        (int64_t)nb_channels * nb_samples > (INT_MAX - (align * nb_channels)) / sample_size)
    143        return AVERROR(EINVAL);
    144 
    145    line_size = planar ? FFALIGN(nb_samples * sample_size,               align) :
    146                         FFALIGN(nb_samples * sample_size * nb_channels, align);
    147    if (linesize)
    148        *linesize = line_size;
    149 
    150    return planar ? line_size * nb_channels : line_size;
    151 }
    152 
    153 int av_samples_fill_arrays(uint8_t **audio_data, int *linesize,
    154                           const uint8_t *buf, int nb_channels, int nb_samples,
    155                           enum AVSampleFormat sample_fmt, int align)
    156 {
    157    int ch, planar, buf_size, line_size;
    158 
    159    planar   = av_sample_fmt_is_planar(sample_fmt);
    160    buf_size = av_samples_get_buffer_size(&line_size, nb_channels, nb_samples,
    161                                          sample_fmt, align);
    162    if (buf_size < 0)
    163        return buf_size;
    164 
    165    if (linesize)
    166        *linesize = line_size;
    167 
    168    memset(audio_data, 0, planar
    169                          ? sizeof(*audio_data) * nb_channels
    170                          : sizeof(*audio_data));
    171 
    172    if (!buf)
    173        return buf_size;
    174 
    175    audio_data[0] = (uint8_t *)buf;
    176    for (ch = 1; planar && ch < nb_channels; ch++)
    177        audio_data[ch] = audio_data[ch-1] + line_size;
    178 
    179    return buf_size;
    180 }
    181 
    182 int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels,
    183                     int nb_samples, enum AVSampleFormat sample_fmt, int align)
    184 {
    185    uint8_t *buf;
    186    int size = av_samples_get_buffer_size(NULL, nb_channels, nb_samples,
    187                                          sample_fmt, align);
    188    if (size < 0)
    189        return size;
    190 
    191    buf = av_malloc(size);
    192    if (!buf)
    193        return AVERROR(ENOMEM);
    194 
    195    size = av_samples_fill_arrays(audio_data, linesize, buf, nb_channels,
    196                                  nb_samples, sample_fmt, align);
    197    if (size < 0) {
    198        av_free(buf);
    199        return size;
    200    }
    201 
    202    av_samples_set_silence(audio_data, 0, nb_samples, nb_channels, sample_fmt);
    203 
    204    return size;
    205 }
    206 
    207 int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels,
    208                                       int nb_samples, enum AVSampleFormat sample_fmt, int align)
    209 {
    210    int ret, nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1;
    211 
    212    *audio_data = av_calloc(nb_planes, sizeof(**audio_data));
    213    if (!*audio_data)
    214        return AVERROR(ENOMEM);
    215    ret = av_samples_alloc(*audio_data, linesize, nb_channels,
    216                           nb_samples, sample_fmt, align);
    217    if (ret < 0)
    218        av_freep(audio_data);
    219    return ret;
    220 }
    221 
    222 int av_samples_copy(uint8_t * const *dst, uint8_t * const *src, int dst_offset,
    223                    int src_offset, int nb_samples, int nb_channels,
    224                    enum AVSampleFormat sample_fmt)
    225 {
    226    int planar      = av_sample_fmt_is_planar(sample_fmt);
    227    int planes      = planar ? nb_channels : 1;
    228    int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels);
    229    int data_size   = nb_samples * block_align;
    230    int i;
    231 
    232    dst_offset *= block_align;
    233    src_offset *= block_align;
    234 
    235    if((dst[0] < src[0] ? src[0] - dst[0] : dst[0] - src[0]) >= data_size) {
    236        for (i = 0; i < planes; i++)
    237            memcpy(dst[i] + dst_offset, src[i] + src_offset, data_size);
    238    } else {
    239        for (i = 0; i < planes; i++)
    240            memmove(dst[i] + dst_offset, src[i] + src_offset, data_size);
    241    }
    242 
    243    return 0;
    244 }
    245 
    246 int av_samples_set_silence(uint8_t * const *audio_data, int offset, int nb_samples,
    247                           int nb_channels, enum AVSampleFormat sample_fmt)
    248 {
    249    int planar      = av_sample_fmt_is_planar(sample_fmt);
    250    int planes      = planar ? nb_channels : 1;
    251    int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels);
    252    int data_size   = nb_samples * block_align;
    253    int fill_char   = (sample_fmt == AV_SAMPLE_FMT_U8 ||
    254                     sample_fmt == AV_SAMPLE_FMT_U8P) ? 0x80 : 0x00;
    255    int i;
    256 
    257    offset *= block_align;
    258 
    259    for (i = 0; i < planes; i++)
    260        memset(audio_data[i] + offset, fill_char, data_size);
    261 
    262    return 0;
    263 }