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