| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "media/base/channel_layout.h" |
| |
| #include <stddef.h> |
| |
| #include "base/check_op.h" |
| #include "base/cxx17_backports.h" |
| #include "base/logging.h" |
| #include "base/notreached.h" |
| |
| namespace media { |
| |
| static const int kLayoutToChannels[] = { |
| 0, // CHANNEL_LAYOUT_NONE |
| 0, // CHANNEL_LAYOUT_UNSUPPORTED |
| 1, // CHANNEL_LAYOUT_MONO |
| 2, // CHANNEL_LAYOUT_STEREO |
| 3, // CHANNEL_LAYOUT_2_1 |
| 3, // CHANNEL_LAYOUT_SURROUND |
| 4, // CHANNEL_LAYOUT_4_0 |
| 4, // CHANNEL_LAYOUT_2_2 |
| 4, // CHANNEL_LAYOUT_QUAD |
| 5, // CHANNEL_LAYOUT_5_0 |
| 6, // CHANNEL_LAYOUT_5_1 |
| 5, // CHANNEL_LAYOUT_5_0_BACK |
| 6, // CHANNEL_LAYOUT_5_1_BACK |
| 7, // CHANNEL_LAYOUT_7_0 |
| 8, // CHANNEL_LAYOUT_7_1 |
| 8, // CHANNEL_LAYOUT_7_1_WIDE |
| 2, // CHANNEL_LAYOUT_STEREO_DOWNMIX |
| 3, // CHANNEL_LAYOUT_2POINT1 |
| 4, // CHANNEL_LAYOUT_3_1 |
| 5, // CHANNEL_LAYOUT_4_1 |
| 6, // CHANNEL_LAYOUT_6_0 |
| 6, // CHANNEL_LAYOUT_6_0_FRONT |
| 6, // CHANNEL_LAYOUT_HEXAGONAL |
| 7, // CHANNEL_LAYOUT_6_1 |
| 7, // CHANNEL_LAYOUT_6_1_BACK |
| 7, // CHANNEL_LAYOUT_6_1_FRONT |
| 7, // CHANNEL_LAYOUT_7_0_FRONT |
| 8, // CHANNEL_LAYOUT_7_1_WIDE_BACK |
| 8, // CHANNEL_LAYOUT_OCTAGONAL |
| 0, // CHANNEL_LAYOUT_DISCRETE |
| 3, // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC |
| 5, // CHANNEL_LAYOUT_4_1_QUAD_SIDE |
| 0, // CHANNEL_LAYOUT_BITSTREAM |
| }; |
| |
| // The channel orderings for each layout as specified by FFmpeg. Each value |
| // represents the index of each channel in each layout. Values of -1 mean the |
| // channel at that index is not used for that layout. For example, the left side |
| // surround sound channel in FFmpeg's 5.1 layout is in the 5th position (because |
| // the order is L, R, C, LFE, LS, RS), so |
| // kChannelOrderings[CHANNEL_LAYOUT_5_1][SIDE_LEFT] = 4; |
| static const int kChannelOrderings[CHANNEL_LAYOUT_MAX + 1][CHANNELS_MAX + 1] = { |
| // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR |
| |
| // CHANNEL_LAYOUT_NONE |
| { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_UNSUPPORTED |
| { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_MONO |
| { -1 , -1 , 0 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_STEREO |
| { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_2_1 |
| { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , 2 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_SURROUND |
| { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_4_0 |
| { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , 3 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_2_2 |
| { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 2 , 3 }, |
| |
| // CHANNEL_LAYOUT_QUAD |
| { 0 , 1 , -1 , -1 , 2 , 3 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_5_0 |
| { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , 3 , 4 }, |
| |
| // CHANNEL_LAYOUT_5_1 |
| { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , -1 , 4 , 5 }, |
| |
| // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR |
| |
| // CHANNEL_LAYOUT_5_0_BACK |
| { 0 , 1 , 2 , -1 , 3 , 4 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_5_1_BACK |
| { 0 , 1 , 2 , 3 , 4 , 5 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_7_0 |
| { 0 , 1 , 2 , -1 , 5 , 6 , -1 , -1 , -1 , 3 , 4 }, |
| |
| // CHANNEL_LAYOUT_7_1 |
| { 0 , 1 , 2 , 3 , 6 , 7 , -1 , -1 , -1 , 4 , 5 }, |
| |
| // CHANNEL_LAYOUT_7_1_WIDE |
| { 0 , 1 , 2 , 3 , -1 , -1 , 6 , 7 , -1 , 4 , 5 }, |
| |
| // CHANNEL_LAYOUT_STEREO_DOWNMIX |
| { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_2POINT1 |
| { 0 , 1 , -1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_3_1 |
| { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_4_1 |
| { 0 , 1 , 2 , 4 , -1 , -1 , -1 , -1 , 3 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_6_0 |
| { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , 5 , 3 , 4 }, |
| |
| // CHANNEL_LAYOUT_6_0_FRONT |
| { 0 , 1 , -1 , -1 , -1 , -1 , 4 , 5 , -1 , 2 , 3 }, |
| |
| // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR |
| |
| // CHANNEL_LAYOUT_HEXAGONAL |
| { 0 , 1 , 2 , -1 , 3 , 4 , -1 , -1 , 5 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_6_1 |
| { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , 6 , 4 , 5 }, |
| |
| // CHANNEL_LAYOUT_6_1_BACK |
| { 0 , 1 , 2 , 3 , 4 , 5 , -1 , -1 , 6 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_6_1_FRONT |
| { 0 , 1 , -1 , 6 , -1 , -1 , 4 , 5 , -1 , 2 , 3 }, |
| |
| // CHANNEL_LAYOUT_7_0_FRONT |
| { 0 , 1 , 2 , -1 , -1 , -1 , 5 , 6 , -1 , 3 , 4 }, |
| |
| // CHANNEL_LAYOUT_7_1_WIDE_BACK |
| { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_OCTAGONAL |
| { 0 , 1 , 2 , -1 , 5 , 6 , -1 , -1 , 7 , 3 , 4 }, |
| |
| // CHANNEL_LAYOUT_DISCRETE |
| { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC |
| { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // CHANNEL_LAYOUT_4_1_QUAD_SIDE |
| { 0 , 1 , -1 , 4 , -1 , -1 , -1 , -1 , -1 , 2 , 3 }, |
| |
| // CHANNEL_LAYOUT_BITSTREAM |
| { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, |
| |
| // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR |
| }; |
| |
| int ChannelLayoutToChannelCount(ChannelLayout layout) { |
| DCHECK_LT(static_cast<size_t>(layout), base::size(kLayoutToChannels)); |
| DCHECK_LE(kLayoutToChannels[layout], kMaxConcurrentChannels); |
| return kLayoutToChannels[layout]; |
| } |
| |
| // Converts a channel count into a channel layout. |
| ChannelLayout GuessChannelLayout(int channels) { |
| switch (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_5_0; |
| case 6: |
| return CHANNEL_LAYOUT_5_1; |
| case 7: |
| return CHANNEL_LAYOUT_6_1; |
| case 8: |
| return CHANNEL_LAYOUT_7_1; |
| default: |
| DVLOG(1) << "Unsupported channel count: " << channels; |
| } |
| return CHANNEL_LAYOUT_UNSUPPORTED; |
| } |
| |
| int ChannelOrder(ChannelLayout layout, Channels channel) { |
| DCHECK_LT(static_cast<size_t>(layout), base::size(kChannelOrderings)); |
| DCHECK_LT(static_cast<size_t>(channel), base::size(kChannelOrderings[0])); |
| return kChannelOrderings[layout][channel]; |
| } |
| |
| const char* ChannelLayoutToString(ChannelLayout layout) { |
| switch (layout) { |
| case CHANNEL_LAYOUT_NONE: |
| return "NONE"; |
| case CHANNEL_LAYOUT_UNSUPPORTED: |
| return "UNSUPPORTED"; |
| case CHANNEL_LAYOUT_MONO: |
| return "MONO"; |
| case CHANNEL_LAYOUT_STEREO: |
| return "STEREO"; |
| case CHANNEL_LAYOUT_2_1: |
| return "2.1"; |
| case CHANNEL_LAYOUT_SURROUND: |
| return "SURROUND"; |
| case CHANNEL_LAYOUT_4_0: |
| return "4.0"; |
| case CHANNEL_LAYOUT_2_2: |
| return "QUAD_SIDE"; |
| case CHANNEL_LAYOUT_QUAD: |
| return "QUAD"; |
| case CHANNEL_LAYOUT_5_0: |
| return "5.0"; |
| case CHANNEL_LAYOUT_5_1: |
| return "5.1"; |
| case CHANNEL_LAYOUT_5_0_BACK: |
| return "5.0_BACK"; |
| case CHANNEL_LAYOUT_5_1_BACK: |
| return "5.1_BACK"; |
| case CHANNEL_LAYOUT_7_0: |
| return "7.0"; |
| case CHANNEL_LAYOUT_7_1: |
| return "7.1"; |
| case CHANNEL_LAYOUT_7_1_WIDE: |
| return "7.1_WIDE"; |
| case CHANNEL_LAYOUT_STEREO_DOWNMIX: |
| return "STEREO_DOWNMIX"; |
| case CHANNEL_LAYOUT_2POINT1: |
| return "2POINT1"; |
| case CHANNEL_LAYOUT_3_1: |
| return "3.1"; |
| case CHANNEL_LAYOUT_4_1: |
| return "4.1"; |
| case CHANNEL_LAYOUT_6_0: |
| return "6.0"; |
| case CHANNEL_LAYOUT_6_0_FRONT: |
| return "6.0_FRONT"; |
| case CHANNEL_LAYOUT_HEXAGONAL: |
| return "HEXAGONAL"; |
| case CHANNEL_LAYOUT_6_1: |
| return "6.1"; |
| case CHANNEL_LAYOUT_6_1_BACK: |
| return "6.1_BACK"; |
| case CHANNEL_LAYOUT_6_1_FRONT: |
| return "6.1_FRONT"; |
| case CHANNEL_LAYOUT_7_0_FRONT: |
| return "7.0_FRONT"; |
| case CHANNEL_LAYOUT_7_1_WIDE_BACK: |
| return "7.1_WIDE_BACK"; |
| case CHANNEL_LAYOUT_OCTAGONAL: |
| return "OCTAGONAL"; |
| case CHANNEL_LAYOUT_DISCRETE: |
| return "DISCRETE"; |
| case CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC: |
| return "STEREO_AND_KEYBOARD_MIC"; |
| case CHANNEL_LAYOUT_4_1_QUAD_SIDE: |
| return "4.1_QUAD_SIDE"; |
| case CHANNEL_LAYOUT_BITSTREAM: |
| return "BITSTREAM"; |
| } |
| NOTREACHED() << "Invalid channel layout provided: " << layout; |
| return ""; |
| } |
| |
| } // namespace media |