Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 "avstring.h"
  27. #include "avutil.h"
  28. #include "channel_layout.h"
  29. #include "bprint.h"
  30. #include "common.h"
  31.  
  32. struct channel_name {
  33.     const char *name;
  34.     const char *description;
  35. };
  36.  
  37. static const struct channel_name channel_names[] = {
  38.      [0] = { "FL",        "front left"            },
  39.      [1] = { "FR",        "front right"           },
  40.      [2] = { "FC",        "front center"          },
  41.      [3] = { "LFE",       "low frequency"         },
  42.      [4] = { "BL",        "back left"             },
  43.      [5] = { "BR",        "back right"            },
  44.      [6] = { "FLC",       "front left-of-center"  },
  45.      [7] = { "FRC",       "front right-of-center" },
  46.      [8] = { "BC",        "back center"           },
  47.      [9] = { "SL",        "side left"             },
  48.     [10] = { "SR",        "side right"            },
  49.     [11] = { "TC",        "top center"            },
  50.     [12] = { "TFL",       "top front left"        },
  51.     [13] = { "TFC",       "top front center"      },
  52.     [14] = { "TFR",       "top front right"       },
  53.     [15] = { "TBL",       "top back left"         },
  54.     [16] = { "TBC",       "top back center"       },
  55.     [17] = { "TBR",       "top back right"        },
  56.     [29] = { "DL",        "downmix left"          },
  57.     [30] = { "DR",        "downmix right"         },
  58.     [31] = { "WL",        "wide left"             },
  59.     [32] = { "WR",        "wide right"            },
  60.     [33] = { "SDL",       "surround direct left"  },
  61.     [34] = { "SDR",       "surround direct right" },
  62.     [35] = { "LFE2",      "low frequency 2"       },
  63. };
  64.  
  65. static const char *get_channel_name(int channel_id)
  66. {
  67.     if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
  68.         return NULL;
  69.     return channel_names[channel_id].name;
  70. }
  71.  
  72. static const struct {
  73.     const char *name;
  74.     int         nb_channels;
  75.     uint64_t     layout;
  76. } channel_layout_map[] = {
  77.     { "mono",        1,  AV_CH_LAYOUT_MONO },
  78.     { "stereo",      2,  AV_CH_LAYOUT_STEREO },
  79.     { "2.1",         3,  AV_CH_LAYOUT_2POINT1 },
  80.     { "3.0",         3,  AV_CH_LAYOUT_SURROUND },
  81.     { "3.0(back)",   3,  AV_CH_LAYOUT_2_1 },
  82.     { "4.0",         4,  AV_CH_LAYOUT_4POINT0 },
  83.     { "quad",        4,  AV_CH_LAYOUT_QUAD },
  84.     { "quad(side)",  4,  AV_CH_LAYOUT_2_2 },
  85.     { "3.1",         4,  AV_CH_LAYOUT_3POINT1 },
  86.     { "5.0",         5,  AV_CH_LAYOUT_5POINT0_BACK },
  87.     { "5.0(side)",   5,  AV_CH_LAYOUT_5POINT0 },
  88.     { "4.1",         5,  AV_CH_LAYOUT_4POINT1 },
  89.     { "5.1",         6,  AV_CH_LAYOUT_5POINT1_BACK },
  90.     { "5.1(side)",   6,  AV_CH_LAYOUT_5POINT1 },
  91.     { "6.0",         6,  AV_CH_LAYOUT_6POINT0 },
  92.     { "6.0(front)",  6,  AV_CH_LAYOUT_6POINT0_FRONT },
  93.     { "hexagonal",   6,  AV_CH_LAYOUT_HEXAGONAL },
  94.     { "6.1",         7,  AV_CH_LAYOUT_6POINT1 },
  95.     { "6.1",         7,  AV_CH_LAYOUT_6POINT1_BACK },
  96.     { "6.1(front)",  7,  AV_CH_LAYOUT_6POINT1_FRONT },
  97.     { "7.0",         7,  AV_CH_LAYOUT_7POINT0 },
  98.     { "7.0(front)",  7,  AV_CH_LAYOUT_7POINT0_FRONT },
  99.     { "7.1",         8,  AV_CH_LAYOUT_7POINT1 },
  100.     { "7.1(wide)",   8,  AV_CH_LAYOUT_7POINT1_WIDE_BACK },
  101.     { "7.1(wide-side)",   8,  AV_CH_LAYOUT_7POINT1_WIDE },
  102.     { "octagonal",   8,  AV_CH_LAYOUT_OCTAGONAL },
  103.     { "downmix",     2,  AV_CH_LAYOUT_STEREO_DOWNMIX, },
  104. };
  105.  
  106. #if FF_API_GET_CHANNEL_LAYOUT_COMPAT
  107. static uint64_t get_channel_layout_single(const char *name, int name_len, int compat)
  108. #else
  109. static uint64_t get_channel_layout_single(const char *name, int name_len)
  110. #endif
  111. {
  112.     int i;
  113.     char *end;
  114.     int64_t layout;
  115.  
  116.     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) {
  117.         if (strlen(channel_layout_map[i].name) == name_len &&
  118.             !memcmp(channel_layout_map[i].name, name, name_len))
  119.             return channel_layout_map[i].layout;
  120.     }
  121.     for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
  122.         if (channel_names[i].name &&
  123.             strlen(channel_names[i].name) == name_len &&
  124.             !memcmp(channel_names[i].name, name, name_len))
  125.             return (int64_t)1 << i;
  126.     i = strtol(name, &end, 10);
  127.  
  128. #if FF_API_GET_CHANNEL_LAYOUT_COMPAT
  129.     if (compat) {
  130.         if (end - name == name_len ||
  131.             (end + 1 - name == name_len && *end  == 'c')) {
  132.             layout = av_get_default_channel_layout(i);
  133.             if (end - name == name_len) {
  134.                 av_log(NULL, AV_LOG_WARNING,
  135.                        "Single channel layout '%.*s' is interpreted as a number of channels, "
  136.                        "switch to the syntax '%.*sc' otherwise it will be interpreted as a "
  137.                        "channel layout number in a later version\n",
  138.                        name_len, name, name_len, name);
  139.                 return layout;
  140.             }
  141.         }
  142.     } else {
  143. #endif
  144.     if ((end + 1 - name == name_len && *end  == 'c'))
  145.         return av_get_default_channel_layout(i);
  146. #if FF_API_GET_CHANNEL_LAYOUT_COMPAT
  147.     }
  148. #endif
  149.  
  150.     layout = strtoll(name, &end, 0);
  151.     if (end - name == name_len)
  152.         return FFMAX(layout, 0);
  153.     return 0;
  154. }
  155.  
  156. #if FF_API_GET_CHANNEL_LAYOUT_COMPAT
  157. uint64_t ff_get_channel_layout(const char *name, int compat)
  158. #else
  159. uint64_t av_get_channel_layout(const char *name)
  160. #endif
  161. {
  162.     const char *n, *e;
  163.     const char *name_end = name + strlen(name);
  164.     int64_t layout = 0, layout_single;
  165.  
  166.     for (n = name; n < name_end; n = e + 1) {
  167.         for (e = n; e < name_end && *e != '+' && *e != '|'; e++);
  168. #if FF_API_GET_CHANNEL_LAYOUT_COMPAT
  169.         layout_single = get_channel_layout_single(n, e - n, compat);
  170. #else
  171.         layout_single = get_channel_layout_single(n, e - n);
  172. #endif
  173.         if (!layout_single)
  174.             return 0;
  175.         layout |= layout_single;
  176.     }
  177.     return layout;
  178. }
  179.  
  180. #if FF_API_GET_CHANNEL_LAYOUT_COMPAT
  181. uint64_t av_get_channel_layout(const char *name)
  182. {
  183.     return ff_get_channel_layout(name, 1);
  184. }
  185. #endif
  186.  
  187. void av_bprint_channel_layout(struct AVBPrint *bp,
  188.                               int nb_channels, uint64_t channel_layout)
  189. {
  190.     int i;
  191.  
  192.     if (nb_channels <= 0)
  193.         nb_channels = av_get_channel_layout_nb_channels(channel_layout);
  194.  
  195.     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
  196.         if (nb_channels    == channel_layout_map[i].nb_channels &&
  197.             channel_layout == channel_layout_map[i].layout) {
  198.             av_bprintf(bp, "%s", channel_layout_map[i].name);
  199.             return;
  200.         }
  201.  
  202.     av_bprintf(bp, "%d channels", nb_channels);
  203.     if (channel_layout) {
  204.         int i, ch;
  205.         av_bprintf(bp, " (");
  206.         for (i = 0, ch = 0; i < 64; i++) {
  207.             if ((channel_layout & (UINT64_C(1) << i))) {
  208.                 const char *name = get_channel_name(i);
  209.                 if (name) {
  210.                     if (ch > 0)
  211.                         av_bprintf(bp, "+");
  212.                     av_bprintf(bp, "%s", name);
  213.                 }
  214.                 ch++;
  215.             }
  216.         }
  217.         av_bprintf(bp, ")");
  218.     }
  219. }
  220.  
  221. void av_get_channel_layout_string(char *buf, int buf_size,
  222.                                   int nb_channels, uint64_t channel_layout)
  223. {
  224.     AVBPrint bp;
  225.  
  226.     av_bprint_init_for_buffer(&bp, buf, buf_size);
  227.     av_bprint_channel_layout(&bp, nb_channels, channel_layout);
  228. }
  229.  
  230. int av_get_channel_layout_nb_channels(uint64_t channel_layout)
  231. {
  232.     return av_popcount64(channel_layout);
  233. }
  234.  
  235. int64_t av_get_default_channel_layout(int nb_channels) {
  236.     int i;
  237.     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
  238.         if (nb_channels == channel_layout_map[i].nb_channels)
  239.             return channel_layout_map[i].layout;
  240.     return 0;
  241. }
  242.  
  243. int av_get_channel_layout_channel_index(uint64_t channel_layout,
  244.                                         uint64_t channel)
  245. {
  246.     if (!(channel_layout & channel) ||
  247.         av_get_channel_layout_nb_channels(channel) != 1)
  248.         return AVERROR(EINVAL);
  249.     channel_layout &= channel - 1;
  250.     return av_get_channel_layout_nb_channels(channel_layout);
  251. }
  252.  
  253. const char *av_get_channel_name(uint64_t channel)
  254. {
  255.     int i;
  256.     if (av_get_channel_layout_nb_channels(channel) != 1)
  257.         return NULL;
  258.     for (i = 0; i < 64; i++)
  259.         if ((1ULL<<i) & channel)
  260.             return get_channel_name(i);
  261.     return NULL;
  262. }
  263.  
  264. const char *av_get_channel_description(uint64_t channel)
  265. {
  266.     int i;
  267.     if (av_get_channel_layout_nb_channels(channel) != 1)
  268.         return NULL;
  269.     for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
  270.         if ((1ULL<<i) & channel)
  271.             return channel_names[i].description;
  272.     return NULL;
  273. }
  274.  
  275. uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
  276. {
  277.     int i;
  278.  
  279.     if (av_get_channel_layout_nb_channels(channel_layout) <= index)
  280.         return 0;
  281.  
  282.     for (i = 0; i < 64; i++) {
  283.         if ((1ULL << i) & channel_layout && !index--)
  284.             return 1ULL << i;
  285.     }
  286.     return 0;
  287. }
  288.  
  289. int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
  290.                                    const char **name)
  291. {
  292.     if (index >= FF_ARRAY_ELEMS(channel_layout_map))
  293.         return AVERROR_EOF;
  294.     if (layout) *layout = channel_layout_map[index].layout;
  295.     if (name)   *name   = channel_layout_map[index].name;
  296.     return 0;
  297. }
  298.