Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/base/channel_layout.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/logging.h"
      9 
     10 namespace media {
     11 
     12 static const int kLayoutToChannels[] = {
     13     0,   // CHANNEL_LAYOUT_NONE
     14     0,   // CHANNEL_LAYOUT_UNSUPPORTED
     15     1,   // CHANNEL_LAYOUT_MONO
     16     2,   // CHANNEL_LAYOUT_STEREO
     17     3,   // CHANNEL_LAYOUT_2_1
     18     3,   // CHANNEL_LAYOUT_SURROUND
     19     4,   // CHANNEL_LAYOUT_4_0
     20     4,   // CHANNEL_LAYOUT_2_2
     21     4,   // CHANNEL_LAYOUT_QUAD
     22     5,   // CHANNEL_LAYOUT_5_0
     23     6,   // CHANNEL_LAYOUT_5_1
     24     5,   // CHANNEL_LAYOUT_5_0_BACK
     25     6,   // CHANNEL_LAYOUT_5_1_BACK
     26     7,   // CHANNEL_LAYOUT_7_0
     27     8,   // CHANNEL_LAYOUT_7_1
     28     8,   // CHANNEL_LAYOUT_7_1_WIDE
     29     2,   // CHANNEL_LAYOUT_STEREO_DOWNMIX
     30     3,   // CHANNEL_LAYOUT_2POINT1
     31     4,   // CHANNEL_LAYOUT_3_1
     32     5,   // CHANNEL_LAYOUT_4_1
     33     6,   // CHANNEL_LAYOUT_6_0
     34     6,   // CHANNEL_LAYOUT_6_0_FRONT
     35     6,   // CHANNEL_LAYOUT_HEXAGONAL
     36     7,   // CHANNEL_LAYOUT_6_1
     37     7,   // CHANNEL_LAYOUT_6_1_BACK
     38     7,   // CHANNEL_LAYOUT_6_1_FRONT
     39     7,   // CHANNEL_LAYOUT_7_0_FRONT
     40     8,   // CHANNEL_LAYOUT_7_1_WIDE_BACK
     41     8,   // CHANNEL_LAYOUT_OCTAGONAL
     42     0,   // CHANNEL_LAYOUT_DISCRETE
     43 };
     44 
     45 // The channel orderings for each layout as specified by FFmpeg.  Each value
     46 // represents the index of each channel in each layout.  Values of -1 mean the
     47 // channel at that index is not used for that layout.For example, the left side
     48 // surround sound channel in FFmpeg's 5.1 layout is in the 5th position (because
     49 // the order is L, R, C, LFE, LS, RS), so
     50 // kChannelOrderings[CHANNEL_LAYOUT_5POINT1][SIDE_LEFT] = 4;
     51 static const int kChannelOrderings[CHANNEL_LAYOUT_MAX][CHANNELS_MAX] = {
     52     // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
     53 
     54     // CHANNEL_LAYOUT_NONE
     55     {  -1 , -1 , -1 , -1  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
     56 
     57     // CHANNEL_LAYOUT_UNSUPPORTED
     58     {  -1 , -1 , -1 , -1  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
     59 
     60     // CHANNEL_LAYOUT_MONO
     61     {  -1 , -1 , 0  , -1  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
     62 
     63     // CHANNEL_LAYOUT_STEREO
     64     {  0  , 1  , -1 , -1  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
     65 
     66     // CHANNEL_LAYOUT_2_1
     67     {  0  , 1  , -1 , -1  , -1 , -1 , -1    , -1    , 2  , -1 , -1 },
     68 
     69     // CHANNEL_LAYOUT_SURROUND
     70     {  0  , 1  , 2  , -1  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
     71 
     72     // CHANNEL_LAYOUT_4_0
     73     {  0  , 1  , 2  , -1  , -1 , -1 , -1    , -1    , 3  , -1 , -1 },
     74 
     75     // CHANNEL_LAYOUT_2_2
     76     {  0  , 1  , -1 , -1  , -1 , -1 , -1    , -1    , -1 , 2  ,  3 },
     77 
     78     // CHANNEL_LAYOUT_QUAD
     79     {  0  , 1  , -1 , -1  , 2  , 3  , -1    , -1    , -1 , -1 , -1 },
     80 
     81     // CHANNEL_LAYOUT_5_0
     82     {  0  , 1  , 2  , -1  , -1 , -1 , -1    , -1    , -1 , 3  ,  4 },
     83 
     84     // CHANNEL_LAYOUT_5_1
     85     {  0  , 1  , 2  , 3   , -1 , -1 , -1    , -1    , -1 , 4  ,  5 },
     86 
     87     // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
     88 
     89     // CHANNEL_LAYOUT_5_0_BACK
     90     {  0  , 1  , 2  , -1  , 3  , 4  , -1    , -1    , -1 , -1 , -1 },
     91 
     92     // CHANNEL_LAYOUT_5_1_BACK
     93     {  0  , 1  , 2  , 3   , 4  , 5  , -1    , -1    , -1 , -1 , -1 },
     94 
     95     // CHANNEL_LAYOUT_7_0
     96     {  0  , 1  , 2  , -1  , 5  , 6  , -1    , -1    , -1 , 3  ,  4 },
     97 
     98     // CHANNEL_LAYOUT_7_1
     99     {  0  , 1  , 2  , 3   , 6  , 7  , -1    , -1    , -1 , 4  ,  5 },
    100 
    101     // CHANNEL_LAYOUT_7_1_WIDE
    102     {  0  , 1  , 2  , 3   , -1 , -1 , 6     , 7     , -1 , 4  ,  5 },
    103 
    104     // CHANNEL_LAYOUT_STEREO_DOWNMIX
    105     {  0  , 1  , -1 , -1  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
    106 
    107     // CHANNEL_LAYOUT_2POINT1
    108     {  0  , 1  , -1 ,  2  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
    109 
    110     // CHANNEL_LAYOUT_3_1
    111     {  0  , 1  ,  2 ,  3  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
    112 
    113     // CHANNEL_LAYOUT_4_1
    114     {  0  , 1  ,  2 ,  4  , -1 , -1 , -1    , -1    ,  3 , -1 , -1 },
    115 
    116     // CHANNEL_LAYOUT_6_0
    117     {  0  , 1  , 2  , -1  , -1 , -1 , -1    , -1    ,  5 , 3  ,  4 },
    118 
    119     // CHANNEL_LAYOUT_6_0_FRONT
    120     {  0  , 1  , -1 , -1  , -1 , -1 ,  4    ,  5    , -1 , 2  ,  3 },
    121 
    122     // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
    123 
    124     // CHANNEL_LAYOUT_HEXAGONAL
    125     {  0  , 1  , 2  , -1  , 3  , 4  , -1    , -1    ,  5 , -1 , -1 },
    126 
    127     // CHANNEL_LAYOUT_6_1
    128     {  0  , 1  , 2  , 3   , -1 , -1 , -1    , -1    ,  6 , 4  ,  5 },
    129 
    130     // CHANNEL_LAYOUT_6_1_BACK
    131     {  0  , 1  , 2  , 3   , 4  , 5  , -1    , -1    ,  6 , -1 , -1 },
    132 
    133     // CHANNEL_LAYOUT_6_1_FRONT
    134     {  0  , 1  , -1 , 6   , -1 , -1 , 4     , 5     , -1 , 2  ,  3 },
    135 
    136     // CHANNEL_LAYOUT_7_0_FRONT
    137     {  0  , 1  , 2  , -1  , -1 , -1 , 5     , 6     , -1 , 3  ,  4 },
    138 
    139     // CHANNEL_LAYOUT_7_1_WIDE_BACK
    140     {  0  , 1  , 2  , 3   , 4  , 5  , 6     , 7     , -1 , -1 , -1 },
    141 
    142     // CHANNEL_LAYOUT_OCTAGONAL
    143     {  0  , 1  , 2  , -1  , 5  , 6  , -1    , -1    ,  7 , 3  ,  4 },
    144 
    145     // CHANNEL_LAYOUT_DISCRETE
    146     {  -1 , -1 , -1 , -1  , -1 , -1 , -1    , -1    , -1 , -1 , -1 },
    147 
    148     // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
    149 };
    150 
    151 int ChannelLayoutToChannelCount(ChannelLayout layout) {
    152   DCHECK_LT(static_cast<size_t>(layout), arraysize(kLayoutToChannels));
    153   return kLayoutToChannels[layout];
    154 }
    155 
    156 // Converts a channel count into a channel layout.
    157 ChannelLayout GuessChannelLayout(int channels) {
    158   switch (channels) {
    159     case 1:
    160       return CHANNEL_LAYOUT_MONO;
    161     case 2:
    162       return CHANNEL_LAYOUT_STEREO;
    163     case 3:
    164       return CHANNEL_LAYOUT_SURROUND;
    165     case 4:
    166       return CHANNEL_LAYOUT_QUAD;
    167     case 5:
    168       return CHANNEL_LAYOUT_5_0;
    169     case 6:
    170       return CHANNEL_LAYOUT_5_1;
    171     case 7:
    172       return CHANNEL_LAYOUT_6_1;
    173     case 8:
    174       return CHANNEL_LAYOUT_7_1;
    175     default:
    176       DVLOG(1) << "Unsupported channel count: " << channels;
    177   }
    178   return CHANNEL_LAYOUT_UNSUPPORTED;
    179 }
    180 
    181 int ChannelOrder(ChannelLayout layout, Channels channel) {
    182   DCHECK_LT(static_cast<size_t>(layout), arraysize(kChannelOrderings));
    183   DCHECK_LT(static_cast<size_t>(channel), arraysize(kChannelOrderings[0]));
    184   return kChannelOrderings[layout][channel];
    185 }
    186 
    187 const char* ChannelLayoutToString(ChannelLayout layout) {
    188   switch (layout) {
    189     case CHANNEL_LAYOUT_NONE:
    190       return "NONE";
    191     case CHANNEL_LAYOUT_UNSUPPORTED:
    192       return "UNSUPPORTED";
    193     case CHANNEL_LAYOUT_MONO:
    194       return "MONO";
    195     case CHANNEL_LAYOUT_STEREO:
    196       return "STEREO";
    197     case CHANNEL_LAYOUT_2_1:
    198       return "2.1";
    199     case CHANNEL_LAYOUT_SURROUND:
    200       return "SURROUND";
    201     case CHANNEL_LAYOUT_4_0:
    202       return "4.0";
    203     case CHANNEL_LAYOUT_2_2:
    204       return "2.2";
    205     case CHANNEL_LAYOUT_QUAD:
    206       return "QUAD";
    207     case CHANNEL_LAYOUT_5_0:
    208       return "5.0";
    209     case CHANNEL_LAYOUT_5_1:
    210       return "5.1";
    211     case CHANNEL_LAYOUT_5_0_BACK:
    212       return "5.0_BACK";
    213     case CHANNEL_LAYOUT_5_1_BACK:
    214       return "5.1_BACK";
    215     case CHANNEL_LAYOUT_7_0:
    216       return "7.0";
    217     case CHANNEL_LAYOUT_7_1:
    218       return "7.1";
    219     case CHANNEL_LAYOUT_7_1_WIDE:
    220       return "7.1_WIDE";
    221     case CHANNEL_LAYOUT_STEREO_DOWNMIX:
    222       return "STEREO_DOWNMIX";
    223     case CHANNEL_LAYOUT_2POINT1:
    224       return "2POINT1";
    225     case CHANNEL_LAYOUT_3_1:
    226       return "3.1";
    227     case CHANNEL_LAYOUT_4_1:
    228       return "4.1";
    229     case CHANNEL_LAYOUT_6_0:
    230       return "6.0";
    231     case CHANNEL_LAYOUT_6_0_FRONT:
    232       return "6.0_FRONT";
    233     case CHANNEL_LAYOUT_HEXAGONAL:
    234       return "HEXAGONAL";
    235     case CHANNEL_LAYOUT_6_1:
    236       return "6.1";
    237     case CHANNEL_LAYOUT_6_1_BACK:
    238       return "6.1_BACK";
    239     case CHANNEL_LAYOUT_6_1_FRONT:
    240       return "6.1_FRONT";
    241     case CHANNEL_LAYOUT_7_0_FRONT:
    242       return "7.0_FRONT";
    243     case CHANNEL_LAYOUT_7_1_WIDE_BACK:
    244       return "7.1_WIDE_BACK";
    245     case CHANNEL_LAYOUT_OCTAGONAL:
    246       return "OCTAGONAL";
    247     case CHANNEL_LAYOUT_DISCRETE:
    248       return "DISCRETE";
    249     case CHANNEL_LAYOUT_MAX:
    250       break;
    251   }
    252   NOTREACHED() << "Invalid channel layout provided: " << layout;
    253   return "";
    254 }
    255 
    256 }  // namespace media
    257