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 };
00052
00053 static const char *get_channel_name(int channel_id)
00054 {
00055 if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
00056 return NULL;
00057 return channel_names[channel_id];
00058 }
00059
00060 static const struct {
00061 const char *name;
00062 int nb_channels;
00063 uint64_t layout;
00064 } channel_layout_map[] = {
00065 { "mono", 1, AV_CH_LAYOUT_MONO },
00066 { "stereo", 2, AV_CH_LAYOUT_STEREO },
00067 { "2.1", 3, AV_CH_LAYOUT_2POINT1 },
00068 { "4.0", 4, AV_CH_LAYOUT_4POINT0 },
00069 { "quad", 4, AV_CH_LAYOUT_QUAD },
00070 { "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK },
00071 { "5.0(side)", 5, AV_CH_LAYOUT_5POINT0 },
00072 { "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK },
00073 { "5.1(side)", 6, AV_CH_LAYOUT_5POINT1 },
00074 { "7.1", 8, AV_CH_LAYOUT_7POINT1 },
00075 { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE },
00076 { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, },
00077 { 0 }
00078 };
00079
00080 static uint64_t get_channel_layout_single(const char *name, int name_len)
00081 {
00082 int i;
00083 char *end;
00084 int64_t layout;
00085
00086 for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map) - 1; i++) {
00087 if (strlen(channel_layout_map[i].name) == name_len &&
00088 !memcmp(channel_layout_map[i].name, name, name_len))
00089 return channel_layout_map[i].layout;
00090 }
00091 for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
00092 if (channel_names[i] &&
00093 strlen(channel_names[i]) == name_len &&
00094 !memcmp(channel_names[i], name, name_len))
00095 return (int64_t)1 << i;
00096 i = strtol(name, &end, 10);
00097 if (end - name == name_len ||
00098 (end + 1 - name == name_len && *end == 'c'))
00099 return av_get_default_channel_layout(i);
00100 layout = strtoll(name, &end, 0);
00101 if (end - name == name_len)
00102 return FFMAX(layout, 0);
00103 return 0;
00104 }
00105
00106 uint64_t av_get_channel_layout(const char *name)
00107 {
00108 const char *n, *e;
00109 const char *name_end = name + strlen(name);
00110 int64_t layout = 0, layout_single;
00111
00112 for (n = name; n < name_end; n = e + 1) {
00113 for (e = n; e < name_end && *e != '+' && *e != '|'; e++);
00114 layout_single = get_channel_layout_single(n, e - n);
00115 if (!layout_single)
00116 return 0;
00117 layout |= layout_single;
00118 }
00119 return layout;
00120 }
00121
00122 void av_get_channel_layout_string(char *buf, int buf_size,
00123 int nb_channels, uint64_t channel_layout)
00124 {
00125 int i;
00126
00127 if (nb_channels <= 0)
00128 nb_channels = av_get_channel_layout_nb_channels(channel_layout);
00129
00130 for (i = 0; channel_layout_map[i].name; i++)
00131 if (nb_channels == channel_layout_map[i].nb_channels &&
00132 channel_layout == channel_layout_map[i].layout) {
00133 av_strlcpy(buf, channel_layout_map[i].name, buf_size);
00134 return;
00135 }
00136
00137 snprintf(buf, buf_size, "%d channels", nb_channels);
00138 if (channel_layout) {
00139 int i, ch;
00140 av_strlcat(buf, " (", buf_size);
00141 for (i = 0, ch = 0; i < 64; i++) {
00142 if ((channel_layout & (UINT64_C(1) << i))) {
00143 const char *name = get_channel_name(i);
00144 if (name) {
00145 if (ch > 0)
00146 av_strlcat(buf, "+", buf_size);
00147 av_strlcat(buf, name, buf_size);
00148 }
00149 ch++;
00150 }
00151 }
00152 av_strlcat(buf, ")", buf_size);
00153 }
00154 }
00155
00156 int av_get_channel_layout_nb_channels(uint64_t channel_layout)
00157 {
00158 int count;
00159 uint64_t x = channel_layout;
00160 for (count = 0; x; count++)
00161 x &= x-1;
00162 return count;
00163 }
00164
00165 int64_t av_get_default_channel_layout(int nb_channels) {
00166 int i;
00167 for (i = 0; channel_layout_map[i].name; i++)
00168 if (nb_channels == channel_layout_map[i].nb_channels)
00169 return channel_layout_map[i].layout;
00170 return 0;
00171 }