00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "avstring.h"
00027 #include "avutil.h"
00028 #include "audioconvert.h"
00029
00030 static const char * const channel_names[] = {
00031 [0] = "FL",
00032 [1] = "FR",
00033 [2] = "FC",
00034 [3] = "LFE",
00035 [4] = "BL",
00036 [5] = "BR",
00037 [6] = "FLC",
00038 [7] = "FRC",
00039 [8] = "BC",
00040 [9] = "SL",
00041 [10] = "SR",
00042 [11] = "TC",
00043 [12] = "TFL",
00044 [13] = "TFC",
00045 [14] = "TFR",
00046 [15] = "TBL",
00047 [16] = "TBC",
00048 [17] = "TBR",
00049 [29] = "DL",
00050 [30] = "DR",
00051 [31] = "WL",
00052 [32] = "WR",
00053 [33] = "SDL",
00054 [34] = "SDR",
00055 };
00056
00057 static const char *get_channel_name(int channel_id)
00058 {
00059 if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
00060 return NULL;
00061 return channel_names[channel_id];
00062 }
00063
00064 static const struct {
00065 const char *name;
00066 int nb_channels;
00067 uint64_t layout;
00068 } channel_layout_map[] = {
00069 { "mono", 1, AV_CH_LAYOUT_MONO },
00070 { "stereo", 2, AV_CH_LAYOUT_STEREO },
00071 { "2.1", 3, AV_CH_LAYOUT_2POINT1 },
00072 { "3.0", 3, AV_CH_LAYOUT_SURROUND },
00073 { "3.0(back)", 3, AV_CH_LAYOUT_2_1 },
00074 { "4.0", 4, AV_CH_LAYOUT_4POINT0 },
00075 { "quad", 4, AV_CH_LAYOUT_QUAD },
00076 { "quad(side)", 4, AV_CH_LAYOUT_2_2 },
00077 { "3.1", 4, AV_CH_LAYOUT_3POINT1 },
00078 { "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK },
00079 { "5.0(side)", 5, AV_CH_LAYOUT_5POINT0 },
00080 { "4.1", 5, AV_CH_LAYOUT_4POINT1 },
00081 { "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK },
00082 { "5.1(side)", 6, AV_CH_LAYOUT_5POINT1 },
00083 { "6.0", 6, AV_CH_LAYOUT_6POINT0 },
00084 { "6.0(front)", 6, AV_CH_LAYOUT_6POINT0_FRONT },
00085 { "hexagonal", 6, AV_CH_LAYOUT_HEXAGONAL },
00086 { "6.1", 7, AV_CH_LAYOUT_6POINT1 },
00087 { "6.1", 7, AV_CH_LAYOUT_6POINT1_BACK },
00088 { "6.1(front)", 7, AV_CH_LAYOUT_6POINT1_FRONT },
00089 { "7.0", 7, AV_CH_LAYOUT_7POINT0 },
00090 { "7.0(front)", 7, AV_CH_LAYOUT_7POINT0_FRONT },
00091 { "7.1", 8, AV_CH_LAYOUT_7POINT1 },
00092 { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE },
00093 { "octagonal", 8, AV_CH_LAYOUT_OCTAGONAL },
00094 { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, },
00095 };
00096
00097 static uint64_t get_channel_layout_single(const char *name, int name_len)
00098 {
00099 int i;
00100 char *end;
00101 int64_t layout;
00102
00103 for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) {
00104 if (strlen(channel_layout_map[i].name) == name_len &&
00105 !memcmp(channel_layout_map[i].name, name, name_len))
00106 return channel_layout_map[i].layout;
00107 }
00108 for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
00109 if (channel_names[i] &&
00110 strlen(channel_names[i]) == name_len &&
00111 !memcmp(channel_names[i], name, name_len))
00112 return (int64_t)1 << i;
00113 i = strtol(name, &end, 10);
00114 if (end - name == name_len ||
00115 (end + 1 - name == name_len && *end == 'c'))
00116 return av_get_default_channel_layout(i);
00117 layout = strtoll(name, &end, 0);
00118 if (end - name == name_len)
00119 return FFMAX(layout, 0);
00120 return 0;
00121 }
00122
00123 uint64_t av_get_channel_layout(const char *name)
00124 {
00125 const char *n, *e;
00126 const char *name_end = name + strlen(name);
00127 int64_t layout = 0, layout_single;
00128
00129 for (n = name; n < name_end; n = e + 1) {
00130 for (e = n; e < name_end && *e != '+' && *e != '|'; e++);
00131 layout_single = get_channel_layout_single(n, e - n);
00132 if (!layout_single)
00133 return 0;
00134 layout |= layout_single;
00135 }
00136 return layout;
00137 }
00138
00139 void av_get_channel_layout_string(char *buf, int buf_size,
00140 int nb_channels, uint64_t channel_layout)
00141 {
00142 int i;
00143
00144 if (nb_channels <= 0)
00145 nb_channels = av_get_channel_layout_nb_channels(channel_layout);
00146
00147 for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
00148 if (nb_channels == channel_layout_map[i].nb_channels &&
00149 channel_layout == channel_layout_map[i].layout) {
00150 av_strlcpy(buf, channel_layout_map[i].name, buf_size);
00151 return;
00152 }
00153
00154 snprintf(buf, buf_size, "%d channels", nb_channels);
00155 if (channel_layout) {
00156 int i, ch;
00157 av_strlcat(buf, " (", buf_size);
00158 for (i = 0, ch = 0; i < 64; i++) {
00159 if ((channel_layout & (UINT64_C(1) << i))) {
00160 const char *name = get_channel_name(i);
00161 if (name) {
00162 if (ch > 0)
00163 av_strlcat(buf, "+", buf_size);
00164 av_strlcat(buf, name, buf_size);
00165 }
00166 ch++;
00167 }
00168 }
00169 av_strlcat(buf, ")", buf_size);
00170 }
00171 }
00172
00173 int av_get_channel_layout_nb_channels(uint64_t channel_layout)
00174 {
00175 int count;
00176 uint64_t x = channel_layout;
00177 for (count = 0; x; count++)
00178 x &= x-1;
00179 return count;
00180 }
00181
00182 int64_t av_get_default_channel_layout(int nb_channels) {
00183 int i;
00184 for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
00185 if (nb_channels == channel_layout_map[i].nb_channels)
00186 return channel_layout_map[i].layout;
00187 return 0;
00188 }