Add audio channel layout API to libavcodec.
[ffmpeg.git] / libavcodec / audioconvert.c
index f6a22bf..9f147a1 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "avcodec.h"
 #include "audioconvert.h"
+#include <libavutil/avstring.h>
 
 typedef struct SampleFmtInfo {
     const char *name;
@@ -70,6 +71,85 @@ void avcodec_sample_fmt_string (char *buf, int buf_size, int sample_fmt)
     }
 }
 
+static const char* const channel_names[]={
+    "FL", "FR", "FC", "LFE", "BL",  "BR",  "FLC", "FRC",
+    "BC", "SL", "SR", "TC",  "TFL", "TFC", "TFR", "TBL",
+    "TBC", "TBR",
+    [29] = "DL",
+    [30] = "DR",
+};
+
+const char *get_channel_name(int channel_id)
+{
+    if (channel_id<0 || channel_id>=FF_ARRAY_ELEMS(channel_names))
+        return NULL;
+    return channel_names[channel_id];
+}
+
+int64_t avcodec_guess_channel_layout(int nb_channels, enum CodecID codec_id, const char *fmt_name)
+{
+    switch(nb_channels) {
+    case 1: return CHANNEL_LAYOUT_MONO;
+    case 2: return CHANNEL_LAYOUT_STEREO;
+    case 3: return CHANNEL_LAYOUT_SURROUND;
+    case 4: return CHANNEL_LAYOUT_QUAD;
+    case 5: return CHANNEL_LAYOUT_5POINT0;
+    case 6: return CHANNEL_LAYOUT_5POINT1;
+    case 8: return CHANNEL_LAYOUT_7POINT1;
+    default: return 0;
+    }
+}
+
+static const struct {
+    const char *name;
+    int         nb_channels;
+    int64_t     layout;
+} const channel_layout_map[] = {
+    { "mono",        1,  CHANNEL_LAYOUT_MONO },
+    { "stereo",      2,  CHANNEL_LAYOUT_STEREO },
+    { "surround",    3,  CHANNEL_LAYOUT_SURROUND },
+    { "quad",        4,  CHANNEL_LAYOUT_QUAD },
+    { "5.0",         5,  CHANNEL_LAYOUT_5POINT0 },
+    { "5.1",         6,  CHANNEL_LAYOUT_5POINT1 },
+    { "5.1+downmix", 8,  CHANNEL_LAYOUT_5POINT1|CHANNEL_LAYOUT_STEREO_DOWNMIX, },
+    { "7.1",         8,  CHANNEL_LAYOUT_7POINT1 },
+    { "7.1(wide)",   8,  CHANNEL_LAYOUT_7POINT1_WIDE },
+    { "7.1+downmix", 10, CHANNEL_LAYOUT_7POINT1|CHANNEL_LAYOUT_STEREO_DOWNMIX, },
+    { 0 }
+};
+
+void avcodec_get_channel_layout_string(char *buf, int buf_size, int nb_channels, int64_t channel_layout)
+{
+    int i;
+
+    if (channel_layout==0)
+        channel_layout = avcodec_guess_channel_layout(nb_channels, CODEC_ID_NONE, NULL);
+
+    for (i=0; channel_layout_map[i].name; i++)
+        if (nb_channels    == channel_layout_map[i].nb_channels &&
+            channel_layout == channel_layout_map[i].layout) {
+            snprintf(buf, buf_size, channel_layout_map[i].name);
+            return;
+        }
+
+    snprintf(buf, buf_size, "%d channels", nb_channels);
+    if (channel_layout) {
+        int i,ch;
+        av_strlcat(buf, " (", buf_size);
+        for(i=0,ch=0; i<64; i++) {
+            if ((channel_layout & (1L<<i))) {
+                const char *name = get_channel_name(i);
+                if (name) {
+                    if (ch>0) av_strlcat(buf, "|", buf_size);
+                    av_strlcat(buf, name, buf_size);
+                }
+                ch++;
+            }
+        }
+        av_strlcat(buf, ")", buf_size);
+    }
+}
+
 struct AVAudioConvert {
     int in_channels, out_channels;
     int fmt_pair;