LCOV - code coverage report
Current view: top level - src/libavutil - channel_layout.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 97 80.4 %
Date: 2017-01-21 09:32:20 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
       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             : /**
      22             :  * @file
      23             :  * audio channel layout utility functions
      24             :  */
      25             : 
      26             : #include <stdint.h>
      27             : 
      28             : #include "avstring.h"
      29             : #include "avutil.h"
      30             : #include "channel_layout.h"
      31             : #include "bprint.h"
      32             : #include "common.h"
      33             : 
      34             : struct channel_name {
      35             :     const char *name;
      36             :     const char *description;
      37             : };
      38             : 
      39             : static const struct channel_name channel_names[] = {
      40             :      [0] = { "FL",        "front left"            },
      41             :      [1] = { "FR",        "front right"           },
      42             :      [2] = { "FC",        "front center"          },
      43             :      [3] = { "LFE",       "low frequency"         },
      44             :      [4] = { "BL",        "back left"             },
      45             :      [5] = { "BR",        "back right"            },
      46             :      [6] = { "FLC",       "front left-of-center"  },
      47             :      [7] = { "FRC",       "front right-of-center" },
      48             :      [8] = { "BC",        "back center"           },
      49             :      [9] = { "SL",        "side left"             },
      50             :     [10] = { "SR",        "side right"            },
      51             :     [11] = { "TC",        "top center"            },
      52             :     [12] = { "TFL",       "top front left"        },
      53             :     [13] = { "TFC",       "top front center"      },
      54             :     [14] = { "TFR",       "top front right"       },
      55             :     [15] = { "TBL",       "top back left"         },
      56             :     [16] = { "TBC",       "top back center"       },
      57             :     [17] = { "TBR",       "top back right"        },
      58             :     [29] = { "DL",        "downmix left"          },
      59             :     [30] = { "DR",        "downmix right"         },
      60             :     [31] = { "WL",        "wide left"             },
      61             :     [32] = { "WR",        "wide right"            },
      62             :     [33] = { "SDL",       "surround direct left"  },
      63             :     [34] = { "SDR",       "surround direct right" },
      64             :     [35] = { "LFE2",      "low frequency 2"       },
      65             : };
      66             : 
      67      120429 : static const char *get_channel_name(int channel_id)
      68             : {
      69      120429 :     if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
      70           0 :         return NULL;
      71      120429 :     return channel_names[channel_id].name;
      72             : }
      73             : 
      74             : static const struct {
      75             :     const char *name;
      76             :     int         nb_channels;
      77             :     uint64_t     layout;
      78             : } channel_layout_map[] = {
      79             :     { "mono",        1,  AV_CH_LAYOUT_MONO },
      80             :     { "stereo",      2,  AV_CH_LAYOUT_STEREO },
      81             :     { "2.1",         3,  AV_CH_LAYOUT_2POINT1 },
      82             :     { "3.0",         3,  AV_CH_LAYOUT_SURROUND },
      83             :     { "3.0(back)",   3,  AV_CH_LAYOUT_2_1 },
      84             :     { "4.0",         4,  AV_CH_LAYOUT_4POINT0 },
      85             :     { "quad",        4,  AV_CH_LAYOUT_QUAD },
      86             :     { "quad(side)",  4,  AV_CH_LAYOUT_2_2 },
      87             :     { "3.1",         4,  AV_CH_LAYOUT_3POINT1 },
      88             :     { "5.0",         5,  AV_CH_LAYOUT_5POINT0_BACK },
      89             :     { "5.0(side)",   5,  AV_CH_LAYOUT_5POINT0 },
      90             :     { "4.1",         5,  AV_CH_LAYOUT_4POINT1 },
      91             :     { "5.1",         6,  AV_CH_LAYOUT_5POINT1_BACK },
      92             :     { "5.1(side)",   6,  AV_CH_LAYOUT_5POINT1 },
      93             :     { "6.0",         6,  AV_CH_LAYOUT_6POINT0 },
      94             :     { "6.0(front)",  6,  AV_CH_LAYOUT_6POINT0_FRONT },
      95             :     { "hexagonal",   6,  AV_CH_LAYOUT_HEXAGONAL },
      96             :     { "6.1",         7,  AV_CH_LAYOUT_6POINT1 },
      97             :     { "6.1(back)",   7,  AV_CH_LAYOUT_6POINT1_BACK },
      98             :     { "6.1(front)",  7,  AV_CH_LAYOUT_6POINT1_FRONT },
      99             :     { "7.0",         7,  AV_CH_LAYOUT_7POINT0 },
     100             :     { "7.0(front)",  7,  AV_CH_LAYOUT_7POINT0_FRONT },
     101             :     { "7.1",         8,  AV_CH_LAYOUT_7POINT1 },
     102             :     { "7.1(wide)",   8,  AV_CH_LAYOUT_7POINT1_WIDE_BACK },
     103             :     { "7.1(wide-side)",   8,  AV_CH_LAYOUT_7POINT1_WIDE },
     104             :     { "octagonal",   8,  AV_CH_LAYOUT_OCTAGONAL },
     105             :     { "hexadecagonal", 16, AV_CH_LAYOUT_HEXADECAGONAL },
     106             :     { "downmix",     2,  AV_CH_LAYOUT_STEREO_DOWNMIX, },
     107             : };
     108             : 
     109        1291 : static uint64_t get_channel_layout_single(const char *name, int name_len)
     110             : {
     111             :     int i;
     112             :     char *end;
     113             :     int64_t layout;
     114             : 
     115       37185 :     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) {
     116       47765 :         if (strlen(channel_layout_map[i].name) == name_len &&
     117       11859 :             !memcmp(channel_layout_map[i].name, name, name_len))
     118          12 :             return channel_layout_map[i].layout;
     119             :     }
     120       47181 :     for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
     121       77787 :         if (channel_names[i].name &&
     122       43803 :             strlen(channel_names[i].name) == name_len &&
     123       11922 :             !memcmp(channel_names[i].name, name, name_len))
     124           4 :             return (int64_t)1 << i;
     125             : 
     126        1275 :     errno = 0;
     127        1275 :     i = strtol(name, &end, 10);
     128             : 
     129        1275 :     if (!errno && (end + 1 - name == name_len && *end  == 'c'))
     130          13 :         return av_get_default_channel_layout(i);
     131             : 
     132        1262 :     errno = 0;
     133        1262 :     layout = strtoll(name, &end, 0);
     134        1262 :     if (!errno && end - name == name_len)
     135        1260 :         return FFMAX(layout, 0);
     136           2 :     return 0;
     137             : }
     138             : 
     139        1283 : uint64_t av_get_channel_layout(const char *name)
     140             : {
     141             :     const char *n, *e;
     142        1283 :     const char *name_end = name + strlen(name);
     143        1283 :     int64_t layout = 0, layout_single;
     144             : 
     145        2568 :     for (n = name; n < name_end; n = e + 1) {
     146        1291 :         for (e = n; e < name_end && *e != '+' && *e != '|'; e++);
     147        1291 :         layout_single = get_channel_layout_single(n, e - n);
     148        1291 :         if (!layout_single)
     149           6 :             return 0;
     150        1285 :         layout |= layout_single;
     151             :     }
     152        1277 :     return layout;
     153             : }
     154             : 
     155     2835160 : void av_bprint_channel_layout(struct AVBPrint *bp,
     156             :                               int nb_channels, uint64_t channel_layout)
     157             : {
     158             :     int i;
     159             : 
     160     2835160 :     if (nb_channels <= 0)
     161     2824819 :         nb_channels = av_get_channel_layout_nb_channels(channel_layout);
     162             : 
     163     7184411 :     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
     164    10100270 :         if (nb_channels    == channel_layout_map[i].nb_channels &&
     165     2947433 :             channel_layout == channel_layout_map[i].layout) {
     166     2803586 :             av_bprintf(bp, "%s", channel_layout_map[i].name);
     167     2803586 :             return;
     168             :         }
     169             : 
     170       31574 :     av_bprintf(bp, "%d channels", nb_channels);
     171       31574 :     if (channel_layout) {
     172             :         int i, ch;
     173       22459 :         av_bprintf(bp, " (");
     174     1459835 :         for (i = 0, ch = 0; i < 64; i++) {
     175     1437376 :             if ((channel_layout & (UINT64_C(1) << i))) {
     176      120367 :                 const char *name = get_channel_name(i);
     177      120367 :                 if (name) {
     178      120367 :                     if (ch > 0)
     179       97908 :                         av_bprintf(bp, "+");
     180      120367 :                     av_bprintf(bp, "%s", name);
     181             :                 }
     182      120367 :                 ch++;
     183             :             }
     184             :         }
     185       22459 :         av_bprintf(bp, ")");
     186             :     }
     187             : }
     188             : 
     189     2832292 : void av_get_channel_layout_string(char *buf, int buf_size,
     190             :                                   int nb_channels, uint64_t channel_layout)
     191             : {
     192             :     AVBPrint bp;
     193             : 
     194     2832292 :     av_bprint_init_for_buffer(&bp, buf, buf_size);
     195     2832292 :     av_bprint_channel_layout(&bp, nb_channels, channel_layout);
     196     2832292 : }
     197             : 
     198     3708329 : int av_get_channel_layout_nb_channels(uint64_t channel_layout)
     199             : {
     200     3708329 :     return av_popcount64(channel_layout);
     201             : }
     202             : 
     203         714 : int64_t av_get_default_channel_layout(int nb_channels) {
     204             :     int i;
     205        1178 :     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
     206        1175 :         if (nb_channels == channel_layout_map[i].nb_channels)
     207         711 :             return channel_layout_map[i].layout;
     208           3 :     return 0;
     209             : }
     210             : 
     211        2145 : int av_get_channel_layout_channel_index(uint64_t channel_layout,
     212             :                                         uint64_t channel)
     213             : {
     214        4290 :     if (!(channel_layout & channel) ||
     215        2145 :         av_get_channel_layout_nb_channels(channel) != 1)
     216           0 :         return AVERROR(EINVAL);
     217        2145 :     channel_layout &= channel - 1;
     218        2145 :     return av_get_channel_layout_nb_channels(channel_layout);
     219             : }
     220             : 
     221          62 : const char *av_get_channel_name(uint64_t channel)
     222             : {
     223             :     int i;
     224          62 :     if (av_get_channel_layout_nb_channels(channel) != 1)
     225           0 :         return NULL;
     226         135 :     for (i = 0; i < 64; i++)
     227         135 :         if ((1ULL<<i) & channel)
     228          62 :             return get_channel_name(i);
     229           0 :     return NULL;
     230             : }
     231             : 
     232           0 : const char *av_get_channel_description(uint64_t channel)
     233             : {
     234             :     int i;
     235           0 :     if (av_get_channel_layout_nb_channels(channel) != 1)
     236           0 :         return NULL;
     237           0 :     for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
     238           0 :         if ((1ULL<<i) & channel)
     239           0 :             return channel_names[i].description;
     240           0 :     return NULL;
     241             : }
     242             : 
     243         594 : uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
     244             : {
     245             :     int i;
     246             : 
     247         594 :     if (av_get_channel_layout_nb_channels(channel_layout) <= index)
     248           0 :         return 0;
     249             : 
     250         941 :     for (i = 0; i < 64; i++) {
     251         941 :         if ((1ULL << i) & channel_layout && !index--)
     252         594 :             return 1ULL << i;
     253             :     }
     254           0 :     return 0;
     255             : }
     256             : 
     257           0 : int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
     258             :                                    const char **name)
     259             : {
     260           0 :     if (index >= FF_ARRAY_ELEMS(channel_layout_map))
     261           0 :         return AVERROR_EOF;
     262           0 :     if (layout) *layout = channel_layout_map[index].layout;
     263           0 :     if (name)   *name   = channel_layout_map[index].name;
     264           0 :     return 0;
     265             : }

Generated by: LCOV version 1.12